Byte-Code-Weberei gegen Lisp-Makros

11

Ich habe über die Bibliotheken gelesen, die für Sprachen wie Java und C # geschrieben wurden, die das Weben von Bytecode verwenden, um beispielsweise Funktionsaufrufe abzufangen, Protokollcode einzufügen usw. Ich habe auch über Lisp / Clojure-Makros in einem gelesen versuchen Sie besser zu verstehen, wie man sie benutzt. Je mehr ich über Makros lese, desto mehr scheint es, dass sie die gleiche Funktionalität bieten wie Bytecode-Webbibliotheken. Mit Funktionalität meine ich die Fähigkeit, Code zur Kompilierungszeit zu manipulieren.

Beispiele für Bibliotheken, die ich mir angesehen habe, sind AspectJ, PostSharp und Cecil.

Gibt es etwas, das mit dem einen und nicht mit dem anderen gemacht werden kann? Lösen sie tatsächlich die gleichen Probleme oder vergleiche ich Äpfel und Orangen?

Mortalapeman
quelle
2
Das Weben von Byte-Codes ist eine
Problemumgehung,
2
@kevincline versuchst du ernsthaft diesen alten Kampf zu beginnen?
Jonathan Henson

Antworten:

10

Das Weben von Bytecodes und Makros sind zwei verschiedene Dinge.

Das Weben von Bytecode ist eine Möglichkeit, Funktionsaufrufe abzufangen, sodass Sie einem Funktionsaufruf vor oder nach der Ausführung der Funktion eine Art von Funktionalität (im Allgemeinen ein Querschnittsthema wie die Protokollierung) hinzufügen können. Das Weben von Bytecode erfolgt auf Bytecode-Ebene, was bedeutet, dass es nach der Kompilierung erfolgt. Die Funktion selbst ist nicht betroffen. Dies ist eine der Techniken, die bei der aspektorientierten Programmierung verwendet werden.

Makros sind eine Möglichkeit, die Syntax einer Sprache zu erweitern. In seiner einfachsten Form ist ein Makro einfach eine Möglichkeit, Tastenanschläge aufzuzeichnen und sie dann mit einem Hotkey wiederzugeben. Sprachmakros funktionieren auf ähnliche Weise. Ein Schlüsselwort oder ein anderes Syntaxkonstrukt ersetzt eine Art Makroerweiterung. Dies ist natürlich zu stark vereinfacht; Ein besseres Beispiel für ein für Lisp spezifisches Makro finden Sie hier .

Robert Harvey
quelle
+1 für die Erwähnung, dass dies ein Schlüssel zur Implementierung von AOP ist.
Jonathan Henson
Und Transaktionen ... vergessen wir nicht die Transaktionen.
Jonathan Henson
3
LISP-Makros sind nichts anderes als eine Möglichkeit, Tastenanschläge aufzuzeichnen.
Kevin Cline
1
Nun, einige grundlegende Konzepte fehlen für die Antwort IMO, diese könnten sein: AST, Reflexion, Metacircularity.
AndreasScheinert
2
@AndreasScheinert: Das OP hat nach keinem dieser Dinge gefragt. Dies ist keine Dissertation; Es ist nur eine Antwort auf die Frage des OP.
Robert Harvey
5

Obwohl sie zum gleichen Zweck verwendet werden können, unterscheiden sich LISP-Makros erheblich von Java-Bytecode-Web-Plugins. LISP-Makros erweitern die LISP-Syntax auf der Ebene des LISP-Quellcodes. Da LISP-Makros auf derselben Ebene wie anderer LISP-Code geschrieben werden, sind sie eine häufig verwendete Sprachfunktion.

Java-Bytecode-Web-Plugins arbeiten auf JVM-Ebene. Während viele Java-Programmierer möglicherweise von anderen geschriebene Bytecode-Web-Plugins verwenden, schreiben nur sehr wenige Java-Programmierer ihre eigenen Bytecode-Web-Plugins.

Einige der von Java-Compiler-Plugins geleisteten Arbeiten lassen sich sehr einfach in dynamischen Sprachen ausführen. Das Abfangen von Funktionsaufrufen ist besonders einfach.

Kevin Cline
quelle
Ich verstehe die technischen Unterschiede zwischen den beiden. Ich habe versucht, die Frage von einem hochrangigen Standpunkt aus zu betrachten. Können beide Tools Code manipulieren, um dieselben Ziele zu erreichen? Gibt es Probleme, die Makros bei der Bytecode-Manipulation nicht lösen können (auf vernünftige und kostengünstige Weise)? Das ist mehr, was ich wollte.
Mortalapeman
@mortalapeman: Die Manipulationen, die in Java und C # über die Änderung des Bytecodes möglich sind, können alle direkt in Sprachen wie Lisp, Ruby, Python, Lua, Javascript durchgeführt werden. Es ist vermutlich möglich, alles zu tun, was ein LISP-Makro über Byte tun kann -Code-Manipulation, aber in der Praxis passiert das nicht.
Kevin Cline
4

Lisp-Makros werden auf Quellcode-Ebene ausgeführt. Wenn Sie ein Makro um einen Code wickeln, können Sie viele Dinge tun. Einschließlich Parsen des Quellcodes, Einfügen von Code, Umschreiben von Code usw.

Wenn Sie Funktionsaufrufe ändern möchten, verwendet Lisp normalerweise zwei Mechanismen:

  • späte Bindungssymbole. Sie können die an ein Symbol gebundene Funktion ändern. Jeder Funktionsaufruf, der ein Symbol durchläuft, verwendet dann die neue Funktion.

  • Lisp-Implementierungen bieten manchmal eine Funktion, die als "Beratung" bezeichnet wird. Dies ermöglicht die Ausführung von Code vor, nach oder um Aufrufe. Zum Beispiel in LispWorks: Beratung .

Auf diese Weise können Sie Anrufe abfangen, ohne den Code auf niedriger Ebene zu manipulieren.

Rainer Joswig
quelle