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

如何获取scala宏来替换方法调用

发布时间:2020-12-16 08:53:48 所属栏目:安全 来源:网络整理
导读:如何让 scala宏替换方法调用? 我的目标是创建一个名为ToStringAdder的特征.假设我有一个具有此特征的对象x,那么当我调用x.add(any)时,我希望宏实际调用x.add(any,string),其中字符串是AST的字符串表示. (这是因为当’any’是一个函数时,我可以有很好的tostr
如何让 scala宏替换方法调用?

我的目标是创建一个名为ToStringAdder的特征.假设我有一个具有此特征的对象x,那么当我调用x.add(any)时,我希望宏实际调用x.add(any,string),其中字符串是AST的字符串表示. (这是因为当’any’是一个函数时,我可以有很好的tostring).

>我已经编写了文档中给出的宏
http://docs.scala-lang.org/overviews/macros/overview.html,
>阅读http://docs.scala-lang.org/sips/pending/self-cleaning-macros.html
>阅读pdfs http://scalamacros.org/paperstalks/2013-04-22-LetOurPowersCombine.pdf.
>我查看了https://github.com/retronym/macrocosm/blob/master/src/main/scala/com/github/retronym/macrocosm/Macrocosm.scala中的代码
>和https://github.com/pniederw/expecty/tree/master/src/main/scala/org/expecty的代码,
但我很遗憾地说我并没有全力以赴
>我看过scaladoc,但是……哇……那很复杂……我怀疑我需要一些重要的时间才能熟悉编译器的工作原理.

除了Expecty之外,我所看到的所有这些示例都是有效地使用静态方法调用:不使用调用宏的对象.
Expecty有以下方法,它给我一个关于如何检测’隐含此’的线索,但我找不到在reify调用中引用它的方法.

private[this] def recordAllValues(expr: Tree): Tree = expr match {
    case New(_) => expr // only record after ctor call
    case Literal(_) => expr // don't record
    // don't record value of implicit "this" added by compiler; couldn't find a better way to detect implicit "this" than via point
    case Select(x@This(_),y) if getPosition(expr).point == getPosition(x).point => expr
    case _ => recordValue(recordSubValues(expr),expr)
  }

那么我该如何将调用替换为调用宏的对象.我目前的代码如下所示,它是reify调用中需要排序的代码

trait ToStringAdder {
  def add(param: Any): Any = macro ToStringAdder.toStringAndValueImpl
  def add(param: Any,toStringBasedOnAST: String): Any ; //This is the actual method I want the above method call to be replaced by
}

object ToStringAdder {
  def toStringAndValueImpl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = {
    import c.universe._
    val paramRep = show(param.tree)
    val paramRepTree = Literal(Constant(paramRep))
    val paramRepExpr = c.Expr[String](paramRepTree)
    //need to put something here 
     reify { c.someMethodCall("something to represent the method any",param.splice,paramRepExpr.splice ) }
  }
}

解决方法

您可以将ToStringAdder实例的Tree作为c.prefix获取.

试试这个:

reify { c.Expr[ToStringAdder](c.prefix.tree).splice.add(param.splice,c.literal(paramRep).splice) }

证明它的工作原理:

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.language.experimental.macros
import reflect.macros.Context

trait ToStringAdder {
  def add(param: Any): Any = macro ToStringAdder.toStringAndValueImpl
  def add(param: Any,toStringBasedOnAST: String): Any ; //This is the actual method I want the above method call to be replaced by
}

object ToStringAdder {
  def toStringAndValueImpl(c: Context)(param: c.Expr[Any]): c.Expr[Any] = {
    import c.universe._
    val paramRep = show(param.tree)
    reify { (c.Expr[ToStringAdder](c.prefix.tree)).splice.add(param.splice,c.literal(paramRep).splice) }
  }
}


// Exiting paste mode,now interpreting.

import scala.language.experimental.macros
import reflect.macros.Context
defined trait ToStringAdder
defined module ToStringAdder

scala> class ToStringAdder1 extends ToStringAdder {
     |   def add(param: Any,toStringBasedOnAST: String): Any = s"param: $param ntoStringBasedOnAST: $toStringBasedOnAST"
     | }
defined class ToStringAdder1

scala> new ToStringAdder1().add( (i: Int) => i*2 )
res0: Any =
param: <function1>
toStringBasedOnAST: ((i: Int) => i.*(2))

(编辑:李大同)

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

    推荐文章
      热点阅读