你可以通过运行时反射来做到这一点,我相信你会得到答案告诉你如何做,如果你想要的话,但这实际上是一个巧妙的用例Scala 2.10 的宏 http://scalamacros.org/,所以就这样。首先假设我们有一个名为ParamMapMaker.scala
:
object ParamMapMaker {
def paramMap: Map[String, Any] = macro paramMapImpl
def paramMapImpl(c: scala.reflect.macros.Context) = {
import c.universe._
val params = c.enclosingMethod match {
case DefDef(_, _, _, ps :: Nil, _, _) =>
ps.map(p =>
reify((
c.Expr[String](Literal(Constant(p.name.decoded))).splice,
c.Expr[Any](Ident(p.symbol)).splice
)).tree
)
case _ => c.abort(c.enclosingPosition, "Can't call paramMap here!")
}
c.Expr[Map[String, Any]](Apply(Select(Ident("Map"), "apply"), params))
}
}
我将把地图键的蛇形外壳作为读者的(简单)练习。
我们还有一个测试文件(名为Test.scala
):
object Test extends App {
def foo(hello: String, answer: Int) = ParamMapMaker.paramMap
println(foo("world", 42))
}
现在我们编译这两个:
scalac -language:experimental.macros ParamMapMaker.scala
scalac Test.scala
当我们跑步时Test
我们会得到以下结果:
Map(hello -> world, answer -> 42)
这样做的妙处在于,没有运行时反射的开销。如果我们编译测试文件-Ymacro-debug-verbose
,我们看到以下代码已经为主体生成(实际上)foo
在编译时:
Map.apply[String, Any](
scala.Tuple2.apply[String, String]("hello", hello),
scala.Tuple2.apply[String, Int]("answer", answer)
)
正如我们所期望的那样。