Metaprogrammierung

Metaprogrammierung ist eine Programmierungstechnik, bei der Computerprogramme haben die Fähigkeit, andere Programme als Daten zu behandeln. Dies bedeutet, dass ein Programm zum Lesen, Generieren, Analysen oder Transformieren anderer Programme entwickelt werden kann und sich selbst während des Ausführens selbst verändert.[1][2] In einigen Fällen können Programmierer die Anzahl der Codezeilen minimieren, um eine Lösung auszudrücken und die Entwicklungszeit zu verkürzen.[3] Außerdem ermöglicht es Programmen, dass Creater Flexibilität ohne Neukompilation effizient umgehen kann.

Die Metaprogrammierung kann verwendet werden, um Berechnungen aus zu verschieben Laufzeit zu Kompilierungszeit, um Code zu generieren, mit Zeitberechnungen kompilierenund um zu aktivieren selbstmodifizierender Code. Die Fähigkeit einer Programmiersprache, ihre eigene Metallanguage zu sein, wird genannt Betrachtung.[4] Reflexion ist ein wertvolles Sprachmerkmal, um die Metaprogrammierung zu erleichtern.

Die Metaprogrammierung war in den 1970er und 1980er Jahren unter Verwendung von Listenverarbeitungssprachen wie z. B. beliebt LISPELN. Lisp -Hardware -Maschinen waren in den 1980er Jahren beliebt und aktivierte Anwendungen, die Code verarbeiten konnten. Sie wurden häufig für verwendet künstliche Intelligenz Anwendungen.

Ansätze

Die Metaprogrammierung ermöglicht es Entwicklern, Programme zu schreiben und Code zu entwickeln, der unter das fällt generische Programmierung Paradigma. Die Programmiersprache selbst als Erstklassiger Datentyp (wie in Lispeln, Prolog, Snobol, oder Rebol) ist auch sehr nützlich; Dies ist bekannt als als Homoikonizität. Die generische Programmierung ruft eine Metaprogrammierungsfunktion innerhalb einer Sprache auf, indem er einen Code schreiben kann, ohne dass Datentypen angegeben werden, da sie bei Verwendung als Parameter geliefert werden können.

Die Metaprogrammierung funktioniert normalerweise auf eine von drei Arten.[5]

  1. Der erste Ansatz besteht darin, die Interna der Laufzeit-Engine dem Programmiercode durchzusetzen Anwendungsprogrammierschnittstellen (Apis) wie das für die .NETZ Il Emitter.
  2. Der zweite Ansatz ist die dynamische Ausführung von Ausdrücken, die Programmierbefehle enthalten, die häufig aus Zeichenfolgen bestehen, aber auch aus anderen Methoden stammen können, die Argumente oder Kontext wie JavaScript verwenden.[6] "Programme können Programme schreiben". Obwohl beide Ansätze in derselben Sprache verwendet werden können, neigen die meisten Sprachen dazu, sich dem einen oder anderen zu neigten.
  3. Der dritte Ansatz besteht darin, die Sprache vollständig auszusteigen. Allgemeiner Zweck Programmumwandlung Systeme wie Compiler, die Sprachbeschreibungen akzeptieren und willkürliche Transformationen in diesen Sprachen durchführen, sind direkte Implementierungen der allgemeinen Metaprogrammierung. Auf diese Weise kann die Metaprogrammierung auf praktisch jede Zielsprache angewendet werden, ohne dass diese Zielsprache eigene Metaprogrammierungsfähigkeiten haben. Man kann dies bei der Arbeit mit der Arbeit sehen Planen und wie es einige Einschränkungen ermöglicht, konfrontiert zu sein C Durch die Verwendung von Konstrukten, die Teil der Schema -Sprache selbst waren, um C zu verlängern C.[7]

Lispeln ist wahrscheinlich die Inbegriff der Sprache mit Metaprogrammiereinrichtungen, sowohl aufgrund ihrer historischen Vorrang und der Einfachheit und Kraft seiner Metaprogrammierung. Bei der Lisp -Metaprogrammierung führt der Unquote -Operator (typischerweise ein Komma) Code ein, der eher zur Programmdefinitionszeit als zur Laufzeit bewertet wird. sehen Selbstbewertende Formen und Zitat in Lisp. Die Metaprogrammierungssprache ist somit identisch mit der Host -Programmiersprache, und vorhandene Lisp -Routinen können bei Bedarf direkt zur Metaprogrammierung wiederverwendet werden. Dieser Ansatz wurde in anderen Sprachen implementiert, indem ein Dolmetscher in das Programm aufgenommen wird, das direkt mit den Daten des Programms funktioniert. Es gibt Implementierungen dieser Art für einige gemeinsame hochrangige Sprachen, wie z. RemobjektePascal -Skript zum Objekt Pascal.

Verwendungen

Codegenerierung

Ein einfaches Beispiel für ein Metaprogramm ist dies POSIX Shell Skript, was ein Beispiel für ist generative Programmierung:

#!/bin/sh # Metaprogramm Echo '#!/bin/sh' > Programmzum i in $ (seq 992) tun  Echo "Echo $ i" >> Programmerledigt CHMOD +X -Programm

Dieses Skript (oder Programm) generiert ein neues 993-Line-Programm, das die Nummern 1–992 ausdruckt. Dies ist nur eine Illustration, wie Sie Code verwenden, um mehr Code zu schreiben. Es ist nicht die effizienteste Möglichkeit, eine Liste von Zahlen auszudrucken. Trotzdem kann ein Programmierer dieses Metaprogramm in weniger als einer Minute schreiben und ausführen und hat in dieser Zeit über 1000 Codezeilen generiert.

A Quine ist eine besondere Art von Metaprogramm, das einen eigenen Quellcode als Ausgabe erzeugt. Quinien sind im Allgemeinen nur von Freizeit- oder theoretischer Interesse.

Nicht alle Metaprogrammierung beinhaltet eine generative Programmierung. Wenn Programme zur Laufzeit verändert werden oder wenn eine inkrementelle Zusammenstellung verfügbar ist (z. B. in C#, Weiter, Frink, Groovig, JavaScript, Lispeln, Elixier, Lua, Nim, Perl, Php, Python, Rebol, Rubin, Rost, SAS, Smalltalk, und Tcl), dann können Techniken verwendet werden, um eine Metaprogrammierung durchzuführen, ohne tatsächlich Quellcode zu generieren.

Ein Stil des generativen Ansatzes besteht darin Domänenspezifische Sprachen (DSLS). Ein ziemlich häufiges Beispiel für die Verwendung von DSLs beinhaltet eine generative Metaprogrammierung: Lex und yacc, zwei Tools, die zur Erzeugung verwendet werden Lexikalanalysatoren und ParserLassen Sie den Benutzer die Sprache verwenden Reguläre Ausdrücke und Kontextfreie Grammatikenund einbetten die komplexen Algorithmen ein, die erforderlich sind, um die Sprache effizient zu analysieren.

Codeinstrumentierung

Eine Verwendung der Metaprogrammierung besteht darin, Programme zu instrumentieren, um dies zu tun Dynamische Programmanalyse.

Verhaltensänderungen

Die Metaprogrammierung kann verwendet werden, um Verhaltensänderungen in einem Programm zu weben, wie in Aspekt-orientiertes Programmieren. Zum Beispiel kann die Metaprogrammierung zum Injektion verwendet werden Feature Flags oder um mögliche Patches zum Beheben von Fehler zu erkunden.[8]

Herausforderungen

Einige argumentieren, dass es eine scharfe Lernkurve gibt, um die Metaprogrammierfunktionen vollständig zu nutzen.[9] Da die Metaprogrammierung mehr Flexibilität und Konfigurierbarkeit zur Laufzeit bietet, kann der Missbrauch oder die falsche Verwendung der Metaprogrammierung zu ungerechtfertigten und unerwarteten Fehlern führen, die für einen durchschnittlichen Entwickler äußerst schwierig sein können. Es kann Risiken im System einführen und es anfälliger machen, wenn sie nicht mit Sorgfalt verwendet werden. Einige der häufigsten Probleme, die aufgrund der falschen Verwendung der Metaprogrammierung auftreten können, sind die Unfähigkeit des Compiler, fehlende Konfigurationsparameter zu identifizieren. Ungültige oder falsche Daten können zu unbekannten Ausnahmen oder unterschiedlichen Ergebnissen führen.[10] Aus diesem Grund glauben einige[9] Dass nur hochqualifizierte Entwickler an der Entwicklung von Funktionen arbeiten sollten, die die Metaprogrammierung in einer Sprache oder Plattform ausüben, und durchschnittliche Entwickler müssen lernen, wie diese Funktionen als Teil der Konvention verwendet werden.

Verwendungszwecke in Programmiersprachen

Makrosysteme

Makroabläufe

Das IBM/360 und Derivate hatten mächtig Makro -Assembler Einrichtungen, die oft zur Erzeugung vollständig verwendet wurden Montagesprache Programme oder Programmabschnitte (beispielsweise für verschiedene Betriebssysteme). Makros zur Verfügung gestellt CICs Transaktionsverarbeitung Das System hatte Assembler-Makros, die COBOL-Anweisungen als Vorverarbeitungsschritt generierten.

Andere Abgeordnete, wie z. Masm, auch Makros unterstützen.

Metaklasse

Metaklasse werden von den folgenden Programmiersprachen bereitgestellt:

Vorlage Metaprogrammierung

Inszenierte Metaprogrammierung

Abhängige Typen

Benutzung von abhängige Typen Ermöglicht das Nachweis, dass generierter Code niemals ungültig ist.[16] Dieser Ansatz ist jedoch Blutungen und wird selten außerhalb der Forschungsprogrammiersprachen gefunden.

Implementierungen

Die Liste der bemerkenswerten Metaprogrammierungssysteme wird beibehalten Liste der Programmtransformationssysteme.

Siehe auch

Verweise

  1. ^ Harald Sondergaard. "Kurs zur Programmanalyse und Transformation". Abgerufen 18. September 2014.
  2. ^ Czarnecki, Krzysztof; Eisenecker, Ulrich W. (2000). Generative Programmierung. ISBN 0-201-30977-7.
  3. ^ Walker, Max. "Die Kunst des Metaprogramms in Java". Neuer Kreis. Abgerufen 28. Januar 2014.
  4. ^ Krauss, Aaron. "Programmierkonzepte: Typesbeobachtung und Reflexion". Die Societa. Abgerufen 14. September 2014.
  5. ^ Joshi, Prateek (5. April 2014). "Was ist Metaprogrammierung? - Teil 2/2". Perpetuales Rätsel. Abgerufen 14. August 2014.
  6. ^ Zum Beispiel Instance_eval in Rubin Nimmt eine Zeichenfolge oder eine anonyme Funktion. "RDOC für die Klasse: BasicObject (Ruby 1.9.3) - Instance_eval". Abgerufen 30. Dezember 2011.
  7. ^ "Kunst der Metaprogrammierung".
  8. ^ Durieux, Thomas; Cornu, Benoit; Seinturier, Lionel; Monperrus, Martin (2017). "Dynamische Patch -Erzeugung für Nullzeigerausnahmen mithilfe von Metaprogrammierung" (PDF). 2017 IEEE 24. Internationale Konferenz für Softwareanalyse, Evolution und Reengineering (saner). IEEE: 349–358. Arxiv:1812.00409. doi:10.1109/saner.2017.7884635. ISBN 978-1-5090-5501-2. S2CID 2736203.
  9. ^ a b Bicking, Ian. "Die Herausforderung der Metaprogrammierung". Ianbicking.org. Abgerufen 21. September 2016.
  10. ^ Terry, Matt (21. August 2013). "Vorsicht der Metaprogrammierung". Medium.com. Medium Corporation. Abgerufen 21. August 2014.
  11. ^ Durch Gemeinsames Lisp -Objektsystem's "Meta -Objektprotokoll"
  12. ^ "C ++ Template Metaprogrammierung". ASZT.inf.ELTE.HU. Abgerufen 2022-07-23.
  13. ^ Lisp (Programmiersprache) "Selbstbewertende Formen und Zitieren", Quasi-Quote-Operator.
  14. ^ "LMS: Programmgenerierung und eingebettete Compiler in Scala". scala-lms.github.io. Abgerufen 2017-12-06.
  15. ^ Rompf, Tiark; Odensky, Martin (Juni 2012). "Leichte modulare Staging: Ein pragmatischer Ansatz zur Erzeugung von Laufzeitcode und kompilierter DSLs". Kommunieren. ACM. 55 (6): 121–130. doi:10.1145/2184319.2184345. ISSN 0001-0782. S2CID 52898203.
  16. ^ Chlipala, Adam (Juni 2010). "UR: Metaprogrammieren statisch mit Type-Aufzeichnungsberechnung" (PDF). ACM Sigplan nennt. PLDI '10. 45 (6): 122–133. doi:10.1145/1809028.1806612. Abgerufen 29. August 2012.

Externe Links