Metaprogrammierung bezieht sich auf eine Vielzahl von Möglichkeiten, wie ein Programm Wissen über sich selbst hat oder sich selbst manipulieren kann.
In Sprachen wie C# ist Reflection eine Form der Metaprogrammierung, da das Programm Informationen über sich selbst untersuchen kann. Zum Beispiel gibt es eine Liste aller Eigenschaften eines Objekts zurück.
In Sprachen wie ActionScript können Sie Funktionen zur Laufzeit auswerten, um neue Programme zu erstellen, wie eval(„x“ + i). DoSomething() würde sich auf ein Objekt namens x1 auswirken, wenn i gleich 1 ist, und auf x2, wenn i gleich 2 ist.
Eine weitere häufige Form der Metaprogrammierung besteht schließlich darin, dass das Programm sich selbst auf nicht-triviale Weise verändern kann. LISP ist dafür sehr bekannt und wurde von Paul Graham vor etwa einem Jahrzehnt propagiert. Ich werde einige seiner spezifischen Aufsätze nachschlagen müssen. Aber die Idee ist, dass das Programm einen anderen Teil des Programms auf der Grundlage seines Zustands ändert. Das erlaubt ein Maß an Flexibilität, um Entscheidungen zur Laufzeit zu treffen, das in den meisten populären Sprachen heute sehr schwierig ist.
Es ist auch erwähnenswert, dass in den guten alten Tagen der Programmierung in reiner Assemblertechnik Programme, die sich zur Laufzeit selbst änderten, notwendig und sehr üblich waren.
Aus Paul Grahams Aufsatz „What Made Lisp Different“:
Viele Sprachen haben etwas, das Makro genannt wird. Aber Lisp-Makros sind einzigartig. Und ob Sie es glauben oder nicht, was sie tun, hat mit den Klammern zu tun. Die Entwickler von Lisp haben all diese Klammern nicht in die Sprache eingebaut, nur um anders zu sein. Für den Blub-Programmierer sieht Lisp-Code seltsam aus. Aber diese Klammern sind aus einem bestimmten Grund da. Sie sind der äußere Beweis für einen grundlegenden Unterschied zwischen Lisp und anderen Sprachen.
Lisp-Code besteht aus Lisp-Datenobjekten. Und zwar nicht in dem trivialen Sinne, dass die Quelldateien Zeichen enthalten und Strings einer der von der Sprache unterstützten Datentypen sind. Lisp-Code besteht, nachdem er vom Parser gelesen wurde, aus Datenstrukturen, die man durchlaufen kann.
Wenn Sie verstehen, wie Compiler arbeiten, ist das, was wirklich passiert, nicht so sehr, dass Lisp eine seltsame Syntax hat, sondern dass Lisp keine Syntax hat. Man schreibt Programme in den Parse-Bäumen, die vom Compiler erzeugt werden, wenn andere Sprachen geparst werden. Aber diese Parse-Bäume sind für Ihre Programme voll zugänglich. Sie können Programme schreiben, die sie manipulieren. In Lisp werden diese Programme Makros genannt. Sie sind Programme, die Programme schreiben.
Programme, die Programme schreiben? Wann würden Sie das jemals tun wollen? Nicht sehr oft, wenn man in Cobol denkt. Die ganze Zeit, wenn man in Lisp denkt. Es wäre praktisch, wenn ich hier ein Beispiel für ein mächtiges Makro geben könnte und sagen könnte: „Da! Wie ist das? Aber wenn ich das täte, würde es für jemanden, der Lisp nicht kennt, nur wie Kauderwelsch aussehen; es ist hier nicht genug Platz, um alles zu erklären, was man wissen muss, um zu verstehen, was es bedeutet. In Ansi Common Lisp habe ich versucht, die Dinge so schnell wie möglich voranzutreiben, und trotzdem bin ich erst auf Seite 160 zu den Makros gekommen.
Aber ich denke, ich kann eine Art von Argumenten liefern, die überzeugend sein könnten. Der Quellcode des Viaweb-Editors bestand wahrscheinlich zu 20-25% aus Makros. Makros sind schwieriger zu schreiben als normale Lisp-Funktionen, und es gilt als schlechter Stil, sie zu verwenden, wenn sie nicht notwendig sind. Jedes Makro in diesem Code ist also da, weil es sein muss. Das bedeutet, dass mindestens 20-25% des Codes in diesem Programm Dinge tun, die man in keiner anderen Sprache so einfach tun kann. Wie skeptisch der Blub-Programmierer auch immer gegenüber meinen Behauptungen über die geheimnisvollen Kräfte von Lisp sein mag, dies sollte ihn neugierig machen. Wir haben diesen Code nicht zu unserem eigenen Vergnügen geschrieben. Wir waren ein winziges Startup-Unternehmen, das so hart programmierte, wie es nur ging, um technische Barrieren zwischen uns und unseren Konkurrenten zu errichten.
Ein misstrauischer Mensch könnte sich fragen, ob es hier einen Zusammenhang gibt. Ein großer Teil unseres Codes machte Dinge, die in anderen Sprachen sehr schwer zu bewerkstelligen sind. Die daraus resultierende Software tat Dinge, die die Software unserer Konkurrenten nicht tun konnte. Vielleicht gab es da eine Art Verbindung. Ich möchte Sie ermutigen, diesen Faden zu verfolgen. Vielleicht steckt mehr hinter dem alten Mann, der auf seinen Krücken herumhumpelt, als man auf den ersten Blick sieht.