Scala Reflection:调用 Function1 的 apply 方法 - 多种选择?
Scala Reflection: Invoking a Function1's apply method - multiple alternatives?
我正在尝试使用 v2.11.6 中的 scala 反射 api 调用一个函数:
import scala.reflect.runtime.{universe => ru}
def f(i: Int) = i + 2
val fn: Any = (f _)
val ref = ru.runtimeMirror(ru.getClass.getClassLoader).reflect(fn)
val apply = ref.symbol.typeSignature.member(ru.TermName("apply"))
当使用 ref.reflectMethod(apply.asMethod)
时,它会抱怨 ref
上 apply
的多个替代方案。检查 apply.asTerm.alternatives
揭示了两种方法,一种带有签名 (x: Int)Int
,另一种带有 (v1: T1)R
。打电话
ref.reflectMethod(apply.asTerm.alternatives(1).asInstanceOf[ru.MethodSymbol])(1)
(与第二个选择)returns正确的结果(3)。然而,调用第一个替代方案会引发异常:java.lang.IllegalArgumentException: object is not an instance of declaring class
这些替代方案是什么?我如何确保始终调用正确的替代方案?使用此方法调用 Function2 或更高版本似乎也有问题,那么正确的方法是什么?
重载apply
方法的原因是Function1
是@specialized
原始类型。
我不知道是否有更好的方法来区分它们,但下面的方法似乎有效,寻找参数擦除为 AnyRef
的替代方法(而不是像 [=15 这样的原语=]):
def invoke(fun1: Any, arg1: Any): Any = {
import scala.reflect.runtime.{universe => ru}
val mirror = ru.runtimeMirror(ru.getClass.getClassLoader)
val ref = mirror.reflect(fn)
val applies = ref.symbol.typeSignature.member(ru.TermName("apply"))
val syms = apply.alternatives.map(_.asMethod)
val sym = syms.find { m =>
m.paramLists match {
case (arg :: Nil) :: Nil
if arg.asTerm.typeSignature.erasure =:= ru.typeOf[AnyRef] => true
case _ => false
}
} getOrElse sys.error("No generic apply method found")
ref.reflectMethod(sym)(arg1)
}
// Test:
val fn: Any = (i: Int) => i + 2
invoke(fn, 1) // res: 3
我正在尝试使用 v2.11.6 中的 scala 反射 api 调用一个函数:
import scala.reflect.runtime.{universe => ru}
def f(i: Int) = i + 2
val fn: Any = (f _)
val ref = ru.runtimeMirror(ru.getClass.getClassLoader).reflect(fn)
val apply = ref.symbol.typeSignature.member(ru.TermName("apply"))
当使用 ref.reflectMethod(apply.asMethod)
时,它会抱怨 ref
上 apply
的多个替代方案。检查 apply.asTerm.alternatives
揭示了两种方法,一种带有签名 (x: Int)Int
,另一种带有 (v1: T1)R
。打电话
ref.reflectMethod(apply.asTerm.alternatives(1).asInstanceOf[ru.MethodSymbol])(1)
(与第二个选择)returns正确的结果(3)。然而,调用第一个替代方案会引发异常:java.lang.IllegalArgumentException: object is not an instance of declaring class
这些替代方案是什么?我如何确保始终调用正确的替代方案?使用此方法调用 Function2 或更高版本似乎也有问题,那么正确的方法是什么?
重载apply
方法的原因是Function1
是@specialized
原始类型。
我不知道是否有更好的方法来区分它们,但下面的方法似乎有效,寻找参数擦除为 AnyRef
的替代方法(而不是像 [=15 这样的原语=]):
def invoke(fun1: Any, arg1: Any): Any = {
import scala.reflect.runtime.{universe => ru}
val mirror = ru.runtimeMirror(ru.getClass.getClassLoader)
val ref = mirror.reflect(fn)
val applies = ref.symbol.typeSignature.member(ru.TermName("apply"))
val syms = apply.alternatives.map(_.asMethod)
val sym = syms.find { m =>
m.paramLists match {
case (arg :: Nil) :: Nil
if arg.asTerm.typeSignature.erasure =:= ru.typeOf[AnyRef] => true
case _ => false
}
} getOrElse sys.error("No generic apply method found")
ref.reflectMethod(sym)(arg1)
}
// Test:
val fn: Any = (i: Int) => i + 2
invoke(fn, 1) // res: 3