Ausgabe
Angenommen, ich habe diesen Code zum Extrahieren des Codes, der eine Variable initialisiert:
def extractBodyImpl[T: Type](expr: Expr[T])(using Quotes) =
import quotes.reflect._
expr.asTerm.underlyingArgument match
case ident @ Ident(_) =>
ident.symbol.tree match
case ValDef(_,_,rhs) => println(rhs)
case DefDef(_,_,_,rhs) => println(rhs)
'{ () }
inline def extractBody[T](inline expr: T) = ${ extractBodyImpl('expr) }
Wenn es für eine Variable aufgerufen wird, die im selben Bereich deklariert ist, funktioniert es wie gewünscht:
@main def hello() =
val x = 1
extractBody(x)
Drucke Some(Literal(Constant(1)))
.
Bei einer Variablen aus dem äußeren Bereich wird jedoch Folgendes ausgegeben None
:
val x = 1
@main def hello() =
extractBody(x)
Wie kann ich es im zweiten Fall zum Laufen bringen?
Lösung
Im Makro geht das nicht. Eine Funktion, die ein Argument erhalten hat, könnte von überall aufgerufen worden sein. Wie würde die statische Analyse auf die Informationen zugreifen, die nur zur Laufzeit verfügbar sind? Die einzig zuverlässige Lösung wäre, den Benutzer zu zwingen, dieses extractBody
Makro direkt nach der Definition des Werts zu erweitern und das Ergebnis an einen Wrapper zu übergeben, der sowohl den Wert als auch seinen Ursprung kombiniert.
Beantwortet von – Mateusz Kubuszok
Antwort geprüft von – Terry (FixError Volunteer)