2017-02-28 57 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' - 一堆会话名称吗? –