Da *_*ike 0 reflection lambda scala
我希望能够解析字符串"x => x + 1",并能够实际将其用作 lambda 函数,如下所示:
val string = "x => x + 1"
val lambda = parseLambda(string)
val numbers = List(1, 2, 3)
val result = numbers.map(lambda) // Should be [2, 3, 4]
Run Code Online (Sandbox Code Playgroud)
我对该函数有以下实现parseLambda:
def parseLambda(string: String): Any => Any = {
val toolbox = runtimeMirror(getClass.getClassLoader).mkToolBox()
val tree = toolbox.parse(string)
val lambdaFunction = toolbox.compile(tree)().asInstanceOf[Any => Any]
lambdaFunction
}
Run Code Online (Sandbox Code Playgroud)
它适用于像"(x: Int) => x * 2"or这样的字符串"(s: String) => s.split(" ")",但如果我省略类型,例如"x => x * 2"or"s => s.split(" ")"我会收到以下错误
';' expected but '=>' found.
Run Code Online (Sandbox Code Playgroud)
有没有办法能够省略字符串中的类型?任何帮助,将不胜感激!
如果没有类型提示,则在 Scala 2 ( https://scastie.scala-lang.org/ChqbxOxRSvGhFTsXeyhOWA ) 和 Scala 3 ( https://scastie.scala-lang.org/1uYVoRXLTeKEwfoPCwrKzQx => x * 2 )中都无法编译。这根本就是糟糕的代码。返回相当无用的消息,但是编译器没有神奇的方法可以猜测输入应该是什么。toolkit.parse
然而,在您的代码中,有一些东西知道类型应该是什么:numbers.
trait TypeName[A] {
def name: String
}
def parseLambda[Input: TypeName](string: String): Input => Any = {
val code = s"""val result: ${implicitly[TypeName[Input]].name} => Any = ${string}
|result
|""".stripMargin
val toolbox = runtimeMirror(getClass.getClassLoader).mkToolBox()
val tree = toolbox.parse(code)
val lambdaFunction = toolbox.compile(tree)().asInstanceOf[Input => Any]
lambdaFunction
}
Run Code Online (Sandbox Code Playgroud)
然后它应该可以工作:
val string = "x => x + 1"
val lambda = parseLambda[Int](string) // Int hinted
val numbers = List(1, 2, 3)
val result = numbers.map(lambda) // Should be [2, 3, 4]
// or
numbers.map(parseLambda(string)) // Int inferred
Run Code Online (Sandbox Code Playgroud)
也就是说,只要您提供正确的TypeName[A]实例,它就应该可以工作。
在 Scala 2 中,它应该与类似的东西一起工作:
object TypeName {
import scala.reflect.runtime.universe._
implicit def provide[A](implicit tag: WeakTypeTag[A]): TypeName[A] =
new TypeName[A] {
def name: String = tag.toString() // should work for simple cases
}
}
Run Code Online (Sandbox Code Playgroud)
对于 Scala 3(您的代码看起来像 Scala 2,但如果您想将其移植到 3),类似于:
object TypeName {
import scala.quoted.*
def provideImpl[A: Type](using quotes: Quotes): Expr[TypeName[A]] =
import quotes.*, quotes.reflect.*
'{
new TypeName[A] {
def name: String = ${ TypeRepr.of[A].show(using TypeReprCode) }
}
}
inline given provide[A]: TypeName[A] = ${ TypeName.provideImpl[A] }
}
Run Code Online (Sandbox Code Playgroud)
(免责声明,我还没有编译它,所以它应该是类似的东西,但可能需要一些调整)。
如果因为您不知道而无法提供该类型怎么办?(例如,如果这个 lambda 发送给您?)
好吧,如果您不知道类型编译器也不会知道,所以您根本无法这样做。
| 归档时间: |
|
| 查看次数: |
107 次 |
| 最近记录: |