gpt4 book ai didi

Scala - 如何在运行时从外部文件编译代码?

转载 作者:行者123 更新时间:2023-12-04 00:07:31 25 4
gpt4 key购买 nike

我想设计一个 Scala 程序,它接受 Scala 文件作为参数,可以自定义程序的执行。特别是,我想在运行时提供包含将由程序调用的方法的实现的文件。如何正确依赖外部文件并在运行时动态调用它们的方法?理想情况下,我还希望这些文件能够依赖于我程序中的方法和类。

示例场景:我有一个包含行 val p: Plant = Greenhouse.getPlant() 的函数,以及 GreenhousegetPlant 一起上课方法在运行时提供的文件之一中定义。在该文件中,方法 getPlant返回 Rose ,其中 Rose <: PlantPlant在原始程序中定义。假设文件仅在运行时而不是在编译时加入,我如何实现(或近似)这种相互依赖性?

最佳答案

以下是仅使用标准 Scala 的方法。不明显的东西都在GreenhouseFactory :

package customizable

abstract class Plant

case class Rose() extends Plant

abstract class Greenhouse {
def getPlant(): Plant
}

case class GreenhouseFactory(implFilename: String) {
import reflect.runtime.currentMirror
import tools.reflect.ToolBox
val toolbox = currentMirror.mkToolBox()
import toolbox.u._
import io.Source

val fileContents = Source.fromFile(implFilename).getLines.mkString("\n")
val tree = toolbox.parse("import customizable._; " + fileContents)
val compiledCode = toolbox.compile(tree)

def make(): Greenhouse = compiledCode().asInstanceOf[Greenhouse]
}

object Main {
def main(args: Array[String]) {
val greenhouseFactory = GreenhouseFactory("external.scala")
val greenhouse = greenhouseFactory.make()
val p = greenhouse.getPlant()

println(p)
}
}

将您的覆盖表达式放在 external.scala 中:
new Greenhouse {
override def getPlant() = new Rose()
}

输出是:
Rose()

唯一棘手的是 GreenhouseFactory需要在前面加上 import语句以提供对外部文件所需的所有类型和符号的访问。为方便起见,将所有这些东西做成一个单一的包。

编译器 ToolBox有点记录 here .除了 weird imports 之外,您唯一真正需要知道的是, 是 toolbox.parse将字符串(Scala 源代码)转换为抽象语法树,以及 toolbox.compile将抽象语法树转换为带有签名的函数 () => Any .由于这是动态编译的代码,因此您必须忍受强制转换 Any到您期望的类型。

关于Scala - 如何在运行时从外部文件编译代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23874281/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com