scala - 如何以编程方式编译和运行 Scala 代码

标签 scala reflection scala-reflect scala-compiler

我有以下代码,我想即时编译并运行它。

object HelloWorld {
  def main(args: Array[String]): Unit = {
    println("Hello, world!")
  }
}

到目前为止,我已经尝试过类似下面的方法:

import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox

object MainScala {
  def main(args: Array[String]): Unit = {
    val toolbox = currentMirror.mkToolBox()
    val source =
      """
        |object HelloWorld {
        |  def main(args: Array[String]): Unit = {
        |    println("Hello, world!")
        |  }
        |}
        |""".stripMargin
    val tree = toolbox.parse(source)
    val binary = toolbox.compile(tree)
    var c = binary.getClass
    val m = c.getMethod("main", classOf[Array[String]])
    val params = Array("Apple", "Banana", "Orange")
    m.invoke(null, null)
  }
}

toolbox.compile(tree) 之后,我无法获得编译代码的 Class 对象。

最佳答案

如果您查看 binary 的类型,您会看到它是 () => Any。因此,当您询问 .getClass 时,您实际上得到了 Function1 的子类,它没有 .main

工具箱不应该这样使用。

https://github.com/scala/scala/blob/2.13.x/src/compiler/scala/tools/reflect/ToolBox.scala#L120-L129

https://docs.scala-lang.org/overviews/reflection/symbols-trees-types.html#tree-creation-via-parse-on-toolboxes

尝试

val source =
  """
    |object HelloWorld {
    |  def main(args: Array[String]): Unit = {
    |    println("Hello, world!")
    |  }
    |}
    |
    |HelloWorld.main(Array())
    |""".stripMargin
val tree = toolbox.parse(source)
val binary = toolbox.compile(tree)
binary() // Hello, world!

val params = """Array("Apple", "Banana", "Orange")"""
val source =
  s"""
    |object HelloWorld {
    |  def main(args: Array[String]): Unit = {
    |    println(args.toList)
    |  }
    |}
    |
    |HelloWorld.main($params)
    |""".stripMargin
val tree = toolbox.parse(source)
val binary = toolbox.compile(tree)
binary() // List(Apple, Banana, Orange)

import scala.reflect.runtime.universe._
val params = q"""Array("Apple", "Banana", "Orange")"""
val tree =
  q"""
    object HelloWorld {
      def main(args: Array[String]): Unit = {
        println(args.toList)
      }
    }

    HelloWorld.main($params)
    """
val binary = toolbox.compile(tree)
binary() // List(Apple, Banana, Orange)

val params = """Array("Apple", "Banana", "Orange")"""
val source =
  """
    |object HelloWorld {
    |  def main(args: Array[String]): Unit = {
    |    println(args.toList)
    |  }
    |}
    |""".stripMargin
val tree = toolbox.parse(source)
val symbol = toolbox.define(tree.asInstanceOf[ImplDef])
val params1 = toolbox.parse(params)
val tree1 = q"$symbol.main($params1)"
val binary = toolbox.compile(tree1)
binary() // List(Apple, Banana, Orange)

关于scala - 如何以编程方式编译和运行 Scala 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57964879/

相关文章:

sql - Slick 中的子查询、具有和分组依据

algorithm - 创建一个函数,但也要确保我实现了另一个函数。是否可以?

pointers - Go中通过反射修改struct中的空指针字段

c# - 在调用方方法中检索原始变量/参数名称(类似于 [CallerMemberName] 属性)

Scala 反射 : Invoking a Function1's apply method - multiple alternatives?

java - 从Scala访问HBase时发生了非法的反射访问操作

scala - 如何强制 F[_] 成为 Monad 的实例

c# - 如何在不使用反射的情况下创建通用属性访问器?

scala - 从 Seq[T] 中提取类型 T

scala - Trees$Literal(反射)在 Scala 2.13.0-M3 中移动了吗?