scala – 多参数和参数列表的Quasiquotes
Quasiquotes是惊人的 – 他们在Scala中编写宏非常少痛苦,而且根据我的经验,他们几乎总是按照我的预期工作.最重要的是,他们现在可以在Scala 2.10中获得
as a plugin.
这个问题是关于我在编写this blog post时遇到的一个小问题.当我找到几分钟时,我会在我的列表中查看这些问题,但我想我会在这里发布,以防其他人可以打败我,并帮助其他遇到同样问题的人. 假设我有一个名称类型对的列表列表: val pss = List( List(newTermName("x") -> typeOf[Int],newTermName("y") -> typeOf[Char]),List(newTermName("z") -> typeOf[String]) ) 我想把它们变成一棵看起来像这样的树: def foo(x: Int,y: Char)(z: String) = ??? 以下工作正常: q"def bar(${pss.head.head._1}: ${pss.head.head._2}) = ???" 也就是说,它构建了以下树: def bar(x: Int) = ??? 这表明我应该能够写出这样的东西: val quoted = pss.map(_.map { case (n,t) => q"$n: $t" }) q"def foo..${quoted.map(ps => q"($ps)")} = 1" 或者更简单,在单个参数列表中有多个参数: q"def baz(..${quoted.head}) = ???" 两者都不起作用 – 我得到这样的错误: <console>:28: error: type mismatch; found : List[c.universe.Typed] required: List[c.universe.ValDef] q"def baz(..${quoted.head}) = ???" ^ 足够公平 – 我可以看到它对于quasiquoter看起来如何构建类型表达式而不是在引用中定义参数.没有任何明显的事情我能想到尝试工作(添加= _,明确键入quasiquote作为ValDef等). 我知道我可以手动构建参数定义: val valDefs = pss.map( _.map { case (n,t) => ValDef(Modifiers(Flag.PARAM),n,TypeTree(t),EmptyTree) } ) 现在baz版本(带有一个参数列表)可以工作: q"def baz(..${valDefs.head}) = ???" 但不是foo版本(具有多个参数列表的版本). 所以这里有两个问题.首先,如何使用quasiquotes将名称类型对转换为引用参数列表上下文之外的参数ValDef?第二,如何将参数定义列表列表转换为多个参数列表? 对于整个该死的东西,很容易回到手动AST构造(例如参见my post),但我希望能够使用quasiquotes代替. 解决方法
以下是您问题的快速解决方案:
val pss = List( List(newTermName("x") -> typeOf[Int],List(newTermName("z") -> typeOf[String]) ) val vparamss: List[List[ValDef]] = pss.map { _.map { case (name,tpe) => q"val $name: $tpe" } } q"def foo(...$vparamss)" 正如你所看到的那样…… $splice允许你定义一个带有多个参数列表的函数.函数参数本身以与常规val相同的方式表示. 另一个例子,其中…… $可能有用: val xy = List(List(q"x"),List(q"y")) q"f(...$xy)" // same as q"f(x)(y)" (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |