【问题标题】:Embedded Scala REPL Interpreter example for 2.102.10 的嵌入式 Scala REPL 解释器示例
【发布时间】:2013-09-08 19:50:39
【问题描述】:

请给出一个代码示例,说明如何以编程方式创建嵌入式 Scala REPL 解释器,该解释器在 Scala 2.10 中工作。 (我花了几个小时梳理各种代码碎片以获得一个工作解释器后添加了这个问答)

【问题讨论】:

    标签: scala read-eval-print-loop


    【解决方案1】:

    基于 Ben 的出色回答,下面是一个帮助程序类,用于简化解释器的启动。用法:

    Repl.run(("e", "Double", 2.71828), ("pi", "Double", 3.1415))
    

    它会自动检测您何时从 SBT 运行并适应。

    Repl.scala:

    import scala.tools.nsc.interpreter.ILoop
    import scala.tools.nsc.Settings
    import java.io.CharArrayWriter
    import java.io.PrintWriter
    
    object Repl {
    
      def run(params: (String, String, Any)*) {
    
        def repl = new ILoop {
          override def loop(): Unit = {
            params.foreach(p => intp.bind(p._1, p._2, p._3))
            super.loop()
          }
        }
    
        val settings = new Settings
        settings.Yreplsync.value = true
    
        // Different settings needed when running from SBT or normally
        if (isRunFromSBT) {
          settings.embeddedDefaults[Repl.type]
        } else {
          settings.usejavacp.value = true
        }
    
        repl.process(settings)
      }
    
      def isRunFromSBT = {
        val c = new CharArrayWriter()
        new Exception().printStackTrace(new PrintWriter(c))
        c.toString().contains("at sbt.")
      }
    
    }
    

    【讨论】:

      【解决方案2】:

      例如Repl.scala:

      import scala.tools.nsc.interpreter._
      import scala.tools.nsc.Settings
      
      
      object Repl extends App {
        def repl = new ILoop {
          override def loop(): Unit = {
            intp.bind("e", "Double", 2.71828)
            super.loop()
          }
        }
      
        val settings = new Settings
        settings.Yreplsync.value = true
      
      
        //use when launching normally outside SBT
        settings.usejavacp.value = true      
      
        //an alternative to 'usejavacp' setting, when launching from within SBT
        //settings.embeddedDefaults[Repl.type]
      
        repl.process(settings)
      }
      

      一些笔记

      • 我选择显示 JLineReader(默认)而不是 SimpleReader,因为它工作得更好,可以正确处理箭头键、删除等。JLine 确实添加了一个 jar 依赖项。
      • 该示例展示了如何将值绑定到 repl(上面的变量 e)。
      • 当我省略 settings.Yreplsync.value = true 时,REPL 挂起并且无用。
      • 根据我的测试,如果 usejavacpembeddedDefaults 设置组合在一起,则会出现错误

      我发现这最容易通过 SBT 进行测试;一个样本build.sbt:

      name := "Repl"
      
      organization := "ExamplesRUs"
      
      scalaVersion := "2.10.2"
      
      libraryDependencies ++= Seq(
       "org.scala-lang" % "scala-compiler" % "2.10.2",
       "org.scala-lang" % "jline" % "2.10.2"
      )
      

      SBT 会话示例:

      > run-main Repl
      [info] Running Repl
      Welcome to Scala version 2.10.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_37).
      Type in expressions to have them evaluated.
      Type :help for more information.
      e: Double = 2.71828
      
      scala> 2 * e
      res1: Double = 5.43656
      
      scala>
      

      【讨论】:

      • 我回答了这个stackoverflow.com/a/18418634/1296806,但我认为我没有尝试过 2.10,而且我总是忘记 -Yrepl-sync 选项。也没有使用 sbt 控制台。谢谢!
      • 还有这个关于绑定值和类加载器的问题stackoverflow.com/a/18503457/1296806 我不知道它是否是好的信息,因为它被忽略了。当你需要的时候,人群在哪里思考?
      • @som-snytt 是的,你的回答是这个例子最有用的来源
      • 不适用于 scala 2.11,因为“方法循环不能覆盖最终方法”
      • @simbo1905 对于 2.11,替代 createInterpreter 并在调用 intp.bind 之前调用 super().createInterpreter()。
      猜你喜欢
      • 1970-01-01
      • 2012-10-08
      • 2020-05-05
      • 1970-01-01
      • 2018-09-08
      • 1970-01-01
      • 2012-04-27
      • 2015-02-08
      • 1970-01-01
      相关资源
      最近更新 更多