使用反射和解释器动态解析字符串并在scala中返回函数 [英] dynamically parse a string and return a function in scala using reflection and interpretors
问题描述
我正在尝试从语法上解释以字符串形式给出的代码. 例如:
I am trying to dinamically interpret code given as a String. Eg:
val myString = "def f(x:Int):Int=x+1".
我正在寻找一种方法,该方法将返回真实函数: 例如:
Im looking for a method that will return the real function out of it: Eg:
val myIncrementFunction = myDarkMagicFunctionThatWillBuildMyFunction(myString)
println(myIncrementFunction(3))
将打印4
用例:我想稍后在代码中使用该解释代码中的一些简单功能.例如,他们可以提供像def fun(x:Int):Int = x + 1这样的字符串,然后使用解释器来编译/执行该代码,然后就可以使用此fun(x ),例如在地图中.
Use case: I want to use some simple functions from that interpreted code later in my code. For example they can provide something like def fun(x: Int): Int = x + 1 as a string, then I use the interpreter to compile/execute that code and then I'd like to be able to use this fun(x) in a map for example.
问题在于该函数类型对我来说是未知的,这是一个大问题,因为我需要从IMain进行回退. 我已经阅读了有关反射,类型系统等的信息,经过一番谷歌搜索后,我到达了这一点.我也检查了twitter的util-eval,但是从他们的测试中的文档和示例中看不到太多,
The problem is that that function type is unknown for me, and this is one of the big problems because I need to cast back from IMain. I've read about reflection, type system and such, and after some googling I reached this point. Also I checked twitter's util-eval but I cant see too much from the docs and the examples in their tests, it's pretty the same thing.
如果我知道类型,我可以做类似的事情
If I know the type I can do something like
val settings = new Settings
val imain = new IMain(settings)
val res = imain.interpret("def f(x:Int):Int=x+1; val ret=f _ ")
val myF = imain.valueOfTerm("ret").get.asInstanceOf[Function[Int,Int]]
println(myF(2))
可以正常工作并打印3,但是我被上面提到的问题所困扰,我不知道该函数的类型,而本示例的工作仅是因为我强制转换为在定义字符串函数时使用的类型测试IMain的工作方式.
which works correctly and prints 3 but I am blocked by the problem I said above, that I dont know the type of the function, and this example works just because I casted to the type I used when I defined the string function for testing how IMain works.
您知道什么方法可以实现此功能吗?
Do you know any method how I could achieve this functionality ?
我是新手,所以如果我写错了,请原谅.
I'm a newbie so please excuse me if I wrote any mistakes.
谢谢
推荐答案
好,我设法实现了想要的功能,我仍在寻找改进此代码的方法,但是此代码段可以满足我的要求.
Ok, I managed to achieve the functionality I wanted, I am still looking for improving this code, but this snippet does what I want.
我使用了scala工具箱和准引用
I used scala toolbox and quasiquotes
import scala.reflect.runtime.universe.{Quasiquote, runtimeMirror}
import scala.tools.reflect.ToolBox
object App {
def main(args: Array[String]): Unit = {
val mirror = runtimeMirror(getClass.getClassLoader)
val tb = ToolBox(mirror).mkToolBox()
val data = Array(1, 2, 3)
println("Data before function applied on it")
println(data.mkString(","))
println("Please enter the map function you want:")
val function = scala.io.StdIn.readLine()
val functionWrapper = "object FunctionWrapper { " + function + "}"
val functionSymbol = tb.define(tb.parse(functionWrapper).asInstanceOf[tb.u.ImplDef])
// Map each element using user specified function
val dataAfterFunctionApplied = data.map(x => tb.eval(q"$functionSymbol.function($x)"))
println("Data after function applied on it")
println(dataAfterFunctionApplied.mkString(","))
}
}
这是终端中的结果:
Data before function applied on it
1,2,3
Please enter the map function you want:
def function(x: Int): Int = x + 2
Data after function applied on it
3,4,5
Process finished with exit code 0
这篇关于使用反射和解释器动态解析字符串并在scala中返回函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!