【问题标题】:Scala quasiquote concatenationScala quasiquote 连接
【发布时间】:2015-05-20 07:42:43
【问题描述】:

我是 scala 宏的新手,我花了几天时间尝试编写我的第一个宏。 我对 quasiquotes 连接有疑问。

有一个case子句的列表,假设如下:

val cases = cq"x => 1 " :: cq"_ => 0 " :: Nil

我需要从中构建一个部分函数。 问题是我不知道如何将它们粘贴到最终的准引用中。 文档说我应该这样做:

q"{ case ..$cases }"

但如果我这样做,它就不起作用。

有没有办法从这样的列表构建 PartialFunction?

感谢您的帮助。

【问题讨论】:

  • 我相信这是正确的做法。你到底有什么错误?
  • 另外你的模式有点奇怪x => 1数学任何表达式,如果你引用一些名为x的本地值你应该使用`x` => 1作为模式
  • 错误如下:宏扩展时出现异常:java.lang.IllegalArgumentException: scala.collection.immutable.List(case (x @ _) => 1, case _ => 0) is模式匹配案例的无效表示。
  • 您使用的是 Scala 2.10 还是 2.11?
  • 如果我这样写,它就可以工作: val case1 = cq"x => 1 " val case2 = cq"_ => 0 " val tree = q""" { case $case1 case $ case2 } """

标签: scala scala-macros scala-quasiquotes


【解决方案1】:

以下内容适用于 2.11.2:

import scala.reflect.macros.Context
object Macros {
    def partial: PartialFunction[Int, Int] = macro partialImpl
    def partialImpl(c: Context): c.Expr[PartialFunction[Int, Int]]= {
        import c.universe._
        val cases = cq"x => 1 " :: cq"_ => 0 " :: Nil
        val pf = q"{ case ..$cases } : PartialFunction[Int, Int]"
        c.Expr[PartialFunction[Int, Int]](pf)

    }
}

然后您可以致电Macros.partial(1),例如,或Macros.partial.isDefinedAt(2)

请注意,为了完成这项工作,我必须在准引用 q"{ case ..$cases } : PartialFunction[Int, Int]" 中明确使用 PartialFunction[Int, Int]。如果没有明确的类型定义,它就无法工作(否则它假定PartialFunction[Any, Int])。

Here 是偏函数的准引用语法规范。它作为纯语法树工作,但显然不能被宏解释为除 PartialFunction[Any, T] 之外的类型化表达式,除非类型明确。

【讨论】:

  • 模式匹配的匿名函数可以是 Function 或 PartialFunction,具体取决于预期的类型。
  • 您的代码有一个错误:PartialFunction[Int, Int]{ case ... } 将创建一个在整个域上定义的 PartialFunction。你想要的是{ case ... }: PartialFunction[Int, Int]
  • 是的。接得好。固定。
猜你喜欢
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 2011-09-27
  • 2021-03-22
相关资源
最近更新 更多