加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 多参数和参数列表的Quasiquotes

发布时间:2020-12-16 08:51:47 所属栏目:安全 来源:网络整理
导读:Quasiquotes是惊人的 – 他们在Scala中编写宏非常少痛苦,而且根据我的经验,他们几乎总是按照我的预期工作.最重要的是,他们现在可以在Scala 2.10中获得 as a plugin. 这个问题是关于我在编写this blog post时遇到的一个小问题.当我找到几分钟时,我会在我的列
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)"

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读