在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")
}
答案 0 :(得分:8)
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
^
答案 1 :(得分:4)
我不确定在没有异常的情况下执行此操作,但实际上您不需要抛出/捕获异常来获取堆栈跟踪:
(new Exception).getStackTrace.toList
答案 2 :(得分:1)
这样你就应该为每个funName
的灵魂Function
,Function1
等重载Function2
。也许一些大师会帮忙?
// 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