Ich habe mit den neuen Makrofunktionen von Scala 2.11 gespielt. Ich wollte sehen, ob ich folgendes schreiben könnte:
%Vor%Ich glaube, ich bin diesem Makro ziemlich nahe gekommen:
%Vor% Dies erzeugt die folgende Ausgabe, wenn sie als forRange(0 to 10) { i => println(i) }
aufgerufen wird (zumindest gibt mir die show
-Funktion den resultierenden Baum an) :
Das sieht so aus, als sollte es funktionieren , aber es gibt einen Konflikt zwischen meinem manuell definierten val i
und dem i
, auf das im verwiesen wird gespleißter Funktionskörper. Ich erhalte den folgenden Fehler:
ReplGlobal.abort: Symbolwert i existiert nicht in $ line38. $ lese $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ $$ iw $$ iw. Fehler: Symbolwert, in dem ich nicht existiere scala.reflect.internal.FatalError: Symbolwert i existiert nicht in $ line38. $ lesen $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw $$ iw.
Und dann ein ziemlich großer Stack-Trace, was zu einer Benachrichtigung über "Abgebrochene Session" führt.
Ich kann nicht sagen, ob dies ein Problem mit meiner Logik ist (Sie können einfach nicht in einen Funktionskörper einfügen, der auf eine geschlossene Variable verweist), oder wenn es sich um einen Fehler bei der neuen Implementierung handelt. Die Fehlerberichterstattung könnte sicherlich besser sein. Es kann durch die Tatsache verschlimmert werden, dass ich dies auf dem Repl laufen lasse.
Ist es möglich, eine Funktion auseinander zu ziehen, den Körper von den geschlossenen Begriffen zu trennen und sie neu zu schreiben, um die Logik direkt in einen resultierenden Baum zu splitten?
Im Zweifelsfall resetAllAttrs
:
Und dann:
%Vor% Wenn Sie einen Baum von einem Ort aus anfassen und an anderer Stelle ablegen, ist es wahrscheinlich notwendig, resetAllAttrs
zu verwenden, um alle Symbole richtig darzustellen.
Oscar Boykin hat auf auf Twitter hingewiesen, dass meine vorherige Antwort nicht mehr funktioniert, und es war sowieso keine sehr vollständige Antwort - sie spricht an Das Problem, auf das das OP auf Scala 2.10 hingewiesen hat, aber es ist nicht vorsichtig in Sachen Hygiene - wenn du iter => println(iter)
geschrieben hast, bekommst du zum Beispiel einen Fehler bei der Kompilierung.
Eine bessere Implementierung für 2.11 würde einen Transformer
verwenden, um den Baum nach dem Entpatchern neu zu schreiben:
Was so funktioniert:
%Vor%Nun spielt es keine Rolle mehr, welchen Variablennamen wir in unserem Funktionsliteral verwenden, da er sowieso nur durch eine neue Variable ersetzt wird.
Tags und Links scala macros expression scala-macros scala-quasiquotes