从函数的返回值中提取符号

时间:2013-03-12 01:23:13

标签: scala macros scala-macros

使用宏我想得到一个通用的解决方案,用于引用案例类数据树的Symbol字段和子字段。

this gist的启发,我创建了以下骨架:

import language.experimental.macros
import reflect.runtime.universe._
import reflect.macros.Context

object SubRef {

  case class SubRef[ SourceT, TargetT ]( symbol : Symbol )

  implicit def functionToSubRef
    [ SourceT, TargetT ]
    ( f : SourceT => TargetT ) 
    : SubRef[ SourceT, TargetT ]
    = macro functionToSubRefMacro[ SourceT, TargetT ]

  def functionToSubRefMacro
    [ SourceT : c.WeakTypeTag, TargetT : c.WeakTypeTag ]
    ( c : Context )
    ( f : c.Expr[ SourceT => TargetT ] )
    : c.Expr[ SubRef[ SourceT, TargetT ] ]
    = ???

}

我希望这个解决方案能够像这样工作:

case class A( b : B )
case class B( c : Int )

val ref : SubRef[ A, Int ] = _.b.c

如果传入函数:

,宏转换应该失败
  • 不是单一表达
  • 不返回符号的值,该符号是源符号的子字段,即targetSymbol.owner[.owner...] == sourceSymbol

缺少的宏实现应该是什么?

1 个答案:

答案 0 :(得分:2)

除了西蒙指出你的符号在2.10中不起作用之外,编写这个宏应该很容易。看起来您已经知道如何执行验证,因此我将省略该部分。

这里真正的挑战是将编译时反射工件(c.universe.Symbol)转换为运行时反射工件(ru.Symbol)。这可以通过具体化来完成。已有c.reifyTreec.reifyType,它们针对树和类型执行此操作,但c.reifySymbol尚不存在。

幸运的是,符号验证应该很容易实现。只需将符号包装在Ident中,即写入Ident(sym),然后在结果上调用c.reifyTree。然后在运行时,你只需从包装树中提取一个符号就可以了。

P.S。现在我没有时间编写完成所有这些事情的代码。如果你们中的任何人都实现了宏并发布了代码,我很乐意删除我的答案并向你们投票:)