Scala REPL中的嵌套环境 [英] Nested environments in Scala REPL
问题描述
是否有可能在Scala REPL中创建( enter )嵌套环境,这样在退出嵌套环境之后,在已存在环境中创建的所有变量绑定都将丢失. ?
Is it possible to create (enter) nested environments in Scala REPL, such that after exiting the nested environment, all variable bindings created within the exited environment will be lost?
这是我希望一个会话的样子:
Here is what I wish a session could look like:
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>
推荐答案
This isn't possible with the current Scala REPL, but you can achieve something similar using the 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
,您仍然可以访问它.
These sessions aren't nested exactly the way you describe, but are easy to track by name, and can overlap. That is after repl.sess.save("first")
, you still have access to the original x
if you don't override it.
玩了更多之后,我得以构筑了一个简单的对象,该对象使用堆栈来跟踪会话并加载/保存它们.可以将其放置在~/.ammonite/predef.sc
中,以使用Ammonite REPL自动加载:
After playing around with it some more, I was able to concoct a simple object that uses a stack to track the sessions and load/save them. It can be placed in ~/.ammonite/predef.sc
to load automatically with the 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._
我没有对此进行严格的测试,因此可能有一个未覆盖的边缘保护套,但是我能够轻松地深入几层然后将其剥离.
I haven't tested this rigorously, so there may be an edge-case that isn't covered, but I was able to go a few levels deep easily and then peel back the layers.
这篇关于Scala REPL中的嵌套环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!