2013-01-01 132 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 
      ^