2017-02-28 5 views
1

はそれがネストされた環境を出した後、終了した環境内で作成されたすべての変数バインディングが失われること(を入力してください)Scalaの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

私はそれを行うためのreplがあるとは思わないが、はいよ! – triggerNZ

+0

私はREPLを利用できませんが、 '{'でブロックを入力して '}'のままにするとうまくいくかもしれません。すべての変数は '{/ * do your stuff * /} 'のようにこのブロック内にしか存在しません。 y // < - これはエラーを起こすはずです ' –

答えて

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に引き続きアクセスできます。


セッションを追跡してロード/保存するためにスタックを使用する単純なオブジェクトを作成することができました。

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._ 

私はこの厳密にテストしていませんので、覆われていないエッジケースがあるかもしれませんが、私は行くことができました。アンモナイトREPLで自動的にロードするために~/.ammonite/predef.scに配置することができますいくつかのレベルの深さを簡単にしてから、レイヤーを剥がします。

+0

ありがとう、それは面白いです。ネストされたスコープ、つまり内側スコープで利用可能な外側スコープからのバインディングが本当に欲しいですが。 –

+0

@TomasMikula 'repl.sess.save(" first ")を呼び出した後でも' x'にアクセスできますので、同様の効果を得ることができます。基本的には、再ロード時にセーブポイントに「ロールバック」することができます。 –

+0

ああ、その場合、グローバル変数(セッション名のスタック)を使って 'enter'と' exit'を実装できますか? –

関連する問題