Embedded Scala REPL Interpreter example for 2.10

前端 未结 2 981
南方客
南方客 2021-02-04 04:05

Please give a code example of how to create an embedded Scala REPL interpreter programmatically, that works in Scala 2.10. (I added this Q&A after spending hours combing

相关标签:
2条回答
  • 2021-02-04 04:25

    Based on Ben's excellent answer, below is a helper class to ease starting the interpreter. Usage:

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

    It automatically detects when you're running from SBT and accommodates.

    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.")
      }
    
    }
    
    0 讨论(0)
  • 2021-02-04 04:36

    Example 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)
    }
    

    Some notes

    • I choose to show the JLineReader (default) rather than SimpleReader because it works much better, correctly handling arrow keys, delete etc. JLine does add an jar dependency.
    • The example shows how to bind values into the repl (variable e above).
    • When I omit settings.Yreplsync.value = true, the REPL hangs and is useless.
    • From my testing, if both usejavacp and embeddedDefaults settings are combined together, an error results

    I find this easiest to test via SBT; a sample 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"
    )
    

    Sample SBT session:

    > 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>
    
    0 讨论(0)
提交回复
热议问题