2013-01-01 134 views
9

在斯卡拉2.9.x中,我写了func函数,它给了我函数的名称,func()被执行,就像FUNC C预处理宏。我明白,在Scala2.10中,我应该能够写出比投掷异常更优雅的东西来完成这项工作。__FUNC__宏在斯卡拉2.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") 
} 

回答

4

我不知道这样做是没有例外,但你实际上并不需要抛出/捕获该异常来获取堆栈跟踪:

(new Exception).getStackTrace.toList 
+1

你甚至可以得到一个堆栈跟踪不会产生异常:有上条条的的getStackTrace()方法,所以你可以做Thread.currentThread()getStackTrace.toList –

1

这样,你应该过载funName为每一位Function的arities:Function1Function2等也许有些大师将帮助?

// 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 
+1

你作弊,你是路过函数转化为宏... – pedrofurla

+0

同意,我对宏的理解还很远,很不完善,但我会改进^) – idonnie

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 
      ^