9 Stimmen

__FUNC__-Makro in Scala 2.10

In Scala 2.9.x habe ich die func-Funktion geschrieben, die mir den Namen der Funktion zurückgibt, in der func() ausgeführt wird, ähnlich dem FUNC C-Präprozessor-Makro. Ich verstehe, dass ich in Scala 2.10 etwas eleganteres schreiben sollte als eine Ausnahme zu werfen, um den Job zu erledigen.

Wie kann ich das machen? Vielen Dank im Voraus für Ihre Hilfe.

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

def func(i_level: Int): String = {
    val s_rien = "FunktionNichtGefunden"
    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")
}

8voto

Eugene Burmako Punkte 12980
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, "keine umgebende Methode")
  }
}

scala> def printEnclosingMethod = macro impl
definierte Term-Makro printEnclosingMethod: Unit

scala> def foo = printEnclosingMethod
foo: Unit

scala> foo
foo

scala> printEnclosingMethod
:32: Fehler: keine umgebende Methode
              printEnclosingMethod

4voto

Kristian Domagala Punkte 3648

Ich bin mir nicht sicher, ob es ohne Ausnahme gemacht werden kann, aber eigentlich musst du die Ausnahme nicht werfen/auffangen, um den Stack-Trace zu erhalten:

(new Exception).getStackTrace.toList

1voto

idonnie Punkte 1695

Auf diese Weise sollten Sie funName für jede einzelne Function-Arität überladen: Function1, Function2 usw. Vielleicht wird ein Guru helfen?

// Makro definieren
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)
  }
}

// ausführen (in einem nächsten Kompiliervorgang)
def haha: Unit = println("Funktionsname: " + Macros.funName(haha _))
haha

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X