2017-02-28 52 views
1

是否有可能創建(進入)在斯卡拉REPL嵌套的環境,使得退出嵌套的環境之後,退出環境中創建的所有變量綁定會丟失?嵌套環境

這是我希望會話可能看起來像:

scala> val x = 1 
x: Int = 1 

scala> enter // How to implement this? 
// Entering nested context (type exit to exit) 

scala> val x = 2 
x: Int = 2 

scala> val y = 3 
y: Int = 3 

scala> exit // How to implement this? 
// Exiting nested context 

scala> assert(x == 1) 

scala> y 
<console>:12: error: not found: value y 
     y 
    ^

scala> 
+2

那太棒了。 –

+1

我不認爲有這樣做的回報,但是請! – triggerNZ

+0

我沒有REPL可用,但也許它會工作,當你用'{'輸入一個塊並用'}'留下時。所有的變量只能在這個塊中生存,就像'{/ *做你的東西* /}; y // < - 這應該會導致一個錯誤' –

回答

1

這是不可能與當前斯卡拉REPL,但你可以使用Ammonite REPL實現類似的東西:

Welcome to the Ammonite Repl 0.8.2 
(Scala 2.12.1 Java 1.8.0_121) 
@ val x = 1 
x: Int = 1 
@ repl.sess.save("first") 
res1_1: ammonite.repl.SessionChanged = 
@ val x = 2 
x: Int = 2 
@ val y = 3 
y: Int = 3 
@ repl.sess.save("second") ; repl.sess.load("first") 
res4_1: ammonite.repl.SessionChanged = 
Removed Imports: Set('y, 'res1_1, 'res1_0) 
@ y 
cmd5.sc:1: not found: value y 
val res5 = y 
     ^
Compilation Failed 
@ x 
res5: Int = 1 

這些會話並非完全按照您描述的方式進行嵌套,而是易於按名稱進行跟蹤,並且可以重疊。即在repl.sess.save("first")之後,如果您不覆蓋它,仍然可以訪問原始x


玩了多一些之後,我能夠炮製一個使用堆棧跟蹤會話和負載的簡單對象/保存。它可以放置在~/.ammonite/predef.sc與菊REPL自動加載:

object SessionStack { 

    case class AmmSession(id: Int = 1) { 
     def name = s"session_${id}" 
     def next = AmmSession(id + 1) 
    } 

    private var sessions = collection.mutable.Stack.empty[AmmSession] 

    private var current = AmmSession() 

    def enter: Unit = { 
     sessions.push(current.copy()) 
     repl.sess.save(current.name) 
     current = current.next 
    } 

    def exit: Unit = if(sessions.nonEmpty) { 
     current = sessions.pop() 
     repl.sess.load(current.name) 
    } else { 
     println("Nothing to exit.") 
    } 

} 
import SessionStack._ 

我沒有測試過嚴格的這一點,所以有可能是未覆蓋的邊緣的情況下,但我可以走了輕鬆深入幾層,然後剝離層。

+0

謝謝,這很有趣。雖然我真的想要嵌套作用域,即外部作用域的綁定可以在內部作用域中使用。 –

+0

@TomasMikula在調用'repl.sess.save(「first」)''後,你仍然可以訪問'x',所以你仍然可以獲得類似的效果,只是不太方便。它實質上允許您在重新加載時「回滾」到保存點。 –

+0

哦,在這種情況下,我可以使用全局變量執行'enter'和'exit' - 一堆會話名稱嗎? –