Scala REPL中的嵌套环境

时间:2017-02-28 03:08:10

标签: scala scala-repl

是否可以在Scala REPL中创建(输入)嵌套环境,以便在退出嵌套环境后,在退出环境中创建的所有变量绑定都将丢失?

以下是我希望会话的内容:

clr.m

1 个答案:

答案 0 :(得分:1)

使用当前的Scala 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中以使用Ammonite 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._

我没有经过严格的测试,所以可能会有一个没有覆盖的边缘情况,但我能够轻松地进入几层,然后剥离层。