简体   繁体   English

如何获取Scala函数的参数/返回类型?

[英]How to get Scala function's parameters / return type?

I have a function, and would like to obtain its parameter types and return type for use in Scala macros. 我有一个函数,并希望获取其参数类型和返回类型以供在Scala宏中使用。

scala> val fn = (a: String, b: Double) => 123
fn: (String, Double) => Int = <function2>

scala> fn.getClass
res1: Class[_ <: (String, Double) => Int] = class $anonfun$1

In the above example, the parameter types and return type already get printed at both lines, but I don't know how to access them. 在上面的例子中,参数类型和返回类型已经在两行打印,但我不知道如何访问它们。 Even with toString I'd be stuck with the <function2> and class $anonfun$1 parts right of the = sign -- otherwise a bit of ugly string parsing might have done. 即使使用toString我仍然会遇到= <function2><function2>class $anonfun$1部分 - 否则可能会有一些丑陋的字符串解析。

I found that the MethodSymbolApi offers a way to extract this information for methods, but it seems like this might not help for this particular case. 我发现MethodSymbolApi提供了一种为方法提取此信息的方法,但似乎这对于这种特殊情况可能没有帮助。

I'm currently looking into AST parsing (as part of scala.meta ) to extract the information, but I'd think this question would seem basic enough to be covered by the standard reflection library, though I've failed to find what I want in there. 我目前正在研究AST解析(作为scala.meta一部分)来提取信息,但我认为这个问题似乎已经基本足以被标准反射库覆盖了,尽管我找不到我的内容想要在那里。 Any ideas? 有任何想法吗?

Edit based on @johanandren's answer: 根据@ johanandren的回答编辑:

I haven't found a neater way to extract them from the TypeTag/Type yet, but this does already work. 我还没有找到一种更简洁的方法从TypeTag / Type中提取它们,但这确实有效。 :) :)

scala> val fn = (a: String, b: Double) => 123
scala> import scala.reflect.runtime.{universe => ru}
scala> def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]
scala> getTypeTag(fn).tpe.toString.split(" => ")
res179: Array[String] = Array((String, Double), Int)

getClass is part of the Java reflection API which does not quite understand Scala types, you should look at the Scala Reflection API instead. getClass是Java反射API的一部分,它不太了解Scala类型,您应该查看Scala Reflection API。 This should get you started, http://docs.scala-lang.org/overviews/reflection/overview.html 这应该可以帮助您入门, http://docs.scala-lang.org/overviews/reflection/overview.html

Not sure but I think a TypeTag for the function type is what you want. 不确定,但我认为函数类型的TypeTag是你想要的。

Just for completness, when you are in Scala REPL, you can access the type as: 只是为了完整性,当您使用Scala REPL时,您可以访问以下类型:

scala> val fn = (a: String, b: Double) => 123
fn: (String, Double) => Int = <function2>

scala> :type fn
(String, Double) => Int

At runtime, Scala compiler won't have complete type information. 在运行时,Scala编译器将不具有完整的类型信息。 So it forms a code snippet fn , ( also does its own symbol table lookups ). 因此它形成了一个代码片段fn ,(也有自己的符号表查找)。 https://github.com/scala/scala/blob/v2.10.5/src/compiler/scala/tools/nsc/interpreter/ILoop.scala#L449 https://github.com/scala/scala/blob/v2.10.5/src/compiler/scala/tools/nsc/interpreter/ILoop.scala#L449

Then passes it to the compiler which then attaches the type information to an implicit evidence type. 然后将其传递给编译器,编译器然后将类型信息附加到implicit evidence类型。

( explained here I want to get the type of a variable at runtime ) (在这里解释我想在运行时获取变量的类型

scala> import scala.reflect.runtime.universe.{TypeTag, typeTag}
import scala.reflect.runtime.universe.{TypeTag, typeTag}

scala> def getTypeTag[T: TypeTag](obj: T) = typeTag[T]
getTypeTag: [T](obj: T)(implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T]

Now we have an evidence that will give us the exact type information: 现在我们有证据可以提供确切的类型信息:

scala> getTypeTag(fn)
res0: reflect.runtime.universe.TypeTag[(String, Double) => Int] = TypeTag[(String, Double) => Int]

scala> val targs = res0.tpe.typeArgs
targs: List[reflect.runtime.universe.Type] = List(String, Double, Int)

Now we can access the types with ease: 现在我们可以轻松访问这些类型:

scala> val (in, out) = (ta.init, ta.last)
in: List[reflect.runtime.universe.Type] = List(String, Double)
out: reflect.runtime.universe.Type = Int

scala> println(s"INPUTS: $in")
INPUTS: List(String, Double)

scala> println(s"OUTPUT: $out")
OUTPUT: Int

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM