首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Scala宏中使用函数参数列表中的新标识符

如何在Scala宏中使用函数参数列表中的新标识符
EN

Stack Overflow用户
提问于 2017-09-26 05:34:30
回答 1查看 189关注 0票数 0

为了学习Scala的宏系统,我想我应该尝试编写一个基本的CPS转换宏。我已经为Clojure编写了一个相当全面的CPS转换框架,所以我非常熟悉CPS转换本身。然而,我遇到了转换函数/方法应用程序的问题。

对于CPS转换,以下形式的函数调用:

代码语言:javascript
复制
cps(f(<a>, <b>, <c>, ...))

需要翻译成以下形式的表达式:

代码语言:javascript
复制
cps(<a>){ $a =>
  cps(<b>){ $b =>
    cps(<c>){ $c =>
      ... => f($a, $b, $c, ...)
    }
  }
}

显然,生成的延续lambda(例如,$a)的参数需要是新的符号,这样它们就不会无意中与词法上下文中的变量名冲突。因此,对于每个参数arg,我都会生成一个新名称:

代码语言:javascript
复制
val name = Ident(TermName(c.freshName))

(其中c是宏的Context),然后我在下面的准引号中使用它:

代码语言:javascript
复制
q"""cps(arg)($name => $remainder)"""

其中remainder指的是计算的其余部分。

宏本身编译得很好,但当我尝试将它与涉及函数应用程序的表达式一起使用时,我得到了以下错误:

代码语言:javascript
复制
... exception during macro expansion:
[error] java.lang.IllegalArgumentException: fresh$macro$1 is not valid representation of a parameter, consider reformatting it into q"val $name: $T = $default" shape

但是,我不认为可以执行推荐的“重新格式化”,因为没有$default可以提供。

下面是一个最小的例子,它说明了我遇到的问题:

代码语言:javascript
复制
def id[A](expr : A) : A = macro idImpl[A]

def idImpl[A](c : blackbox.Context)(expr : c.Expr[A]) : c.Expr[A] = {
  import c.universe._

  val name = Ident(TermName(c.freshName))

  //c.Expr(q"""val $name = $expr; $name""")
  c.Expr(q"""($name => $name)($expr)""")
}

请注意,如果您将lambda表达式替换为注释行,它将起作用。

所以我的问题是:如何将freshName生成的名称用作匿名函数的参数名称?

EN

回答 1

Stack Overflow用户

发布于 2017-09-26 08:31:32

我认为您需要一个val $name: $T = _形式的ValDef,其中_NoTree表示。使用_初始化变量是有效的Scala,将对null的引用和对数字的引用设置为0 (即默认值),但当有ValDef(例如函数参数)但没有合理的默认值时,也用作内部占位符。

我在用手机,所以我不能测试。在任何情况下,如果NoTree不起作用,您都可以对REPL中的值q"a: Any => a"进行解构,以查找编译器通常设置为默认值的内容。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46414528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档