【问题标题】:__FUNC__ macro in Scala 2.10Scala 2.10 中的 __FUNC__ 宏
【发布时间】:2013-01-01 22:08:49
【问题描述】:

在 Scala 2.9.x 中,我编写了 func 函数,它返回了执行 func() 的函数的名称,就像 FUNC C 预处理器宏一样。我知道在 Scala2.10 中我应该能够写出比抛出异常更优雅的东西来完成这项工作。

我该怎么做?提前感谢您的帮助。

object TestMyLog extends App {
    val MatchFunc = """(.+)\(.+""".r

def func(i_level: Int): String = {
    val s_rien = "functionNotFound"
    try {
    throw new Exception()
    } catch {
    case unknwn => unknwn.getStackTrace.toList.apply(i_level).toString match {
            case MatchFunc(funcs) => funcs.split('.').toList.last
        case _ => s_rien
    }
    } finally {
    s_rien      
    }
}

def tracedFunction1 = func(1)
def tracedFunction2 = func(1)

println(tracedFunction1)
assert(tracedFunction1=="tracedFunction1")
println(tracedFunction2)
assert(tracedFunction2=="tracedFunction2")
}

【问题讨论】:

    标签: scala scala-2.10


    【解决方案1】:
    import scala.reflect.macros.Context
    import scala.language.experimental.macros
    
    def impl(c: Context) = {
      import c.universe._
      c.enclosingMethod match {
        case DefDef(_, name, _, _, _, _) =>
          c.universe.reify(println(c.literal(name.toString).splice))
        case _ => c.abort(c.enclosingPosition, "no enclosing method")
      }
    }
    
    scala> def printEnclosingMethod = macro impl
    defined term macro printEnclosingMethod: Unit
    
    scala> def foo = printEnclosingMethod
    foo: Unit
    
    scala> foo
    foo
    
    scala> printEnclosingMethod
    <console>:32: error: no enclosing method
                  printEnclosingMethod
                  ^
    

    【讨论】:

      【解决方案2】:

      我不确定是否要在没有异常的情况下执行此操作,但您实际上并不需要抛出/捕获异常来获取堆栈跟踪:

      (new Exception).getStackTrace.toList
      

      【讨论】:

      • 您甚至可以在不创建异常的情况下获得堆栈跟踪:Thread 上有一个 getStackTrace() 方法,因此您可以执行 Thread.currentThread().getStackTrace.toList
      【解决方案3】:

      这样您应该为每个Function 的arities 重载funNameFunction1Function2 等。也许一些大师会有所帮助?

      // define macro
      import scala.language.experimental.macros
      import scala.reflect.macros.Context
      object Macros {
        def funName(xs: Function0[_]) = macro funName_impl
        def funName_impl(c: Context)(xs: c.Expr[Function0[_]]) = { 
          c.literal(xs.tree.children.head.toString.split("\\.").last)
        }
      }
      
      // exec (in a next compile run)
      def haha: Unit = println("Function name: " + Macros.funName(haha _))
      haha
      

      【讨论】:

      • 同意,我对宏的理解远非完美,但我会改进^)
      猜你喜欢
      • 2012-07-25
      • 1970-01-01
      • 2012-11-30
      • 2013-07-08
      • 1970-01-01
      • 1970-01-01
      • 2013-10-27
      • 1970-01-01
      • 2013-02-24
      相关资源
      最近更新 更多