Scala 宏在运行时访问函数的源代码

Scala 宏在运行时访问函数的源代码,scala,reflection,macros,scala-macros,Scala,Reflection,Macros,Scala Macros,我想使用Scala宏访问函数f的源代码 以下是我的问题的简化示例: def logFImplementation(f: => Boolean) { val sourceCodeOfF: String = ... // <-- how to get source code of f?? println("Scala source of f=" + sourceCodeOfF) } 它应该打印: Scala source of f=val i: Int = 5; im

我想使用Scala宏访问函数f的源代码

以下是我的问题的简化示例:

def logFImplementation(f: => Boolean) {
    val sourceCodeOfF: String = ... // <-- how to get source code of f??

    println("Scala source of f=" + sourceCodeOfF)
}
它应该打印:

Scala source of f=val i: Int = 5; immutable.this.List.apply[Int](1, 2, 3); true
(现在我进行了测试,它对
{val I=5;List(1,2,3);true}.logValueImpl
非常有效,但是对于
f.logValueImpl
它只打印
f

谢谢你的建议。

我严重怀疑这是否可能

首先,宏是编译时的东西。它们所做的只是转换程序包含的抽象语法树。这正是您能够执行
{val i=5;List(1,2,3);true}的原因。logValueImpl
:AST就在这里,所以将其打印为字符串没有困难。但宏无法解析运行时值,因为运行时没有宏

其次,绝对没有理由相信
f
是Scala代码。我可以像这样从Java调用您的函数(我不确定是否所有名称都正确,但想法仍然是一样的):

someObject.logf实现(新scala.Function0(){
@凌驾
公共布尔应用(){
//用Java做一些事情
}
});

(这是可能的,因为内部按名称调用参数被转换为
scala.Function0
对象)。在这种情况下,您希望您的函数输出什么?

这可能是“线程巫术”,因为这个问题已经很老了。我不得不努力解决这个问题

import scala.reflect.macros.blackbox.Context
import scala.language.experimental.macros
object FunctionWrapper {

  implicit def apply[P, R](fn: P => R): FunctionWrapper[P, R] = macro apply_impl[P, R]

  def apply_impl[P: c.WeakTypeTag, R: c.WeakTypeTag](c: Context)(fn: c.Expr[P => R]): 
                  c.Expr[FunctionWrapper[P, R]] = {
    import c.universe._
     c.Expr(q" new FunctionWrapper($fn, ${show(fn.tree))})")
  }
}
class FunctionWrapper[P, R](val fn: P => R, description: String) 
      extends Function1[P, R] {
  def apply(p: P) = fn(p)
  override def toString = description
}
正在使用的示例(必须在单独的编译模块中)为:


非常感谢你的回答。是的,一切都是正确的,它是函数0,我完全同意你的答案。您要问的问题是:您是否看到了任何可能的方法/技术来获取编译器从中创建Function0的Scala代码?(并且在运行时可以访问此字符串)不,没有办法。Scala不会将AST保存到类文件中(而且很可能没有空间存放它),而且您无法从字节码可靠地恢复Scala代码,即使它确实保存了AST,您也无法使用宏从
f
中提取AST,因为宏在编译时工作,而
f
的实际类(以及实现)也是如此是未知的UTI运行时。@Vladimitavevevevev,我支持你的观点,但我想指出的是,在
scala.meta
(下一代scala)中,将有这样一种可能性(即将AST带到运行时),因此肯定有一个位置。无论如何,你所说的一切到目前为止都是正确的。再次感谢你们的回答。也许我可以重新表述我的问题:如何创建宏
logImplementation{val I=5;List(1,2,3);true}
,它将打印通过的代码并返回计算的布尔值?(如果您愿意,我可以在StackOverflow创建下一个问题,这样社区就不会失去您的建议。)我发布了其他问题:
someObject.logFImplementation(new scala.Function0<Boolean>() {
    @Override
    public Boolean apply() {
        // do some things in Java
    }
});
import scala.reflect.macros.blackbox.Context
import scala.language.experimental.macros
object FunctionWrapper {

  implicit def apply[P, R](fn: P => R): FunctionWrapper[P, R] = macro apply_impl[P, R]

  def apply_impl[P: c.WeakTypeTag, R: c.WeakTypeTag](c: Context)(fn: c.Expr[P => R]): 
                  c.Expr[FunctionWrapper[P, R]] = {
    import c.universe._
     c.Expr(q" new FunctionWrapper($fn, ${show(fn.tree))})")
  }
}
class FunctionWrapper[P, R](val fn: P => R, description: String) 
      extends Function1[P, R] {
  def apply(p: P) = fn(p)
  override def toString = description
}
 object FunctionWrapperUser {
  def main(args: Array[String]): Unit = {
    val double = FunctionWrapper((i: Int) => i * 2)
    println(s"double to String is $double")
    println(double(4))
  }
}