Metaprogrammering hänvisar till en mängd olika sätt på vilka ett program har kunskap om sig självt eller kan manipulera sig självt.
I språk som C# är reflektion en form av metaprogrammering eftersom programmet kan undersöka information om sig självt. Till exempel att returnera en lista över alla egenskaper hos ett objekt.
I språk som ActionScript kan du utvärdera funktioner vid körning för att skapa nya program, till exempel eval(”x” + i). DoSomething() skulle påverka ett objekt som heter x1 när i är 1 och x2 när i är 2.
Enlig en annan vanlig form av metaprogrammering är när programmet kan ändra sig självt på icke-triviala sätt. LISP är välkänt för detta och är något som Paul Graham förespråkade för ungefär tio år sedan. Jag måste leta upp några av hans specifika uppsatser. Men tanken är att programmet skulle ändra en annan del av programmet baserat på dess tillstånd. Detta ger en nivå av flexibilitet att fatta beslut vid körning som är mycket svår i de flesta populära språk idag.
Det är också värt att notera att på den gamla goda tiden när man programmerade i ren assembler var program som ändrade sig själva vid körning nödvändiga och mycket vanliga.
Från Paul Grahams uppsats ”What Made Lisp Different”:
Många språk har något som kallas för ett makro. Men Lisp-makron är unika. Och tro det eller ej, vad de gör är relaterat till parenteserna. Lispkonstruktörerna lade inte in alla dessa parenteser i språket bara för att vara annorlunda. För Blub-programmeraren ser Lisp-kod konstig ut. Men parenteserna finns där av en anledning. De är det yttre beviset på en grundläggande skillnad mellan Lisp och andra språk.
Lisp-kod består av Lisp-dataobjekt. Och inte i den triviala meningen att källfilerna innehåller tecken, och strängar är en av de datatyper som stöds av språket. Lisp-kod, efter att den har lästs av parsern, består av datastrukturer som du kan gå igenom.
Om du förstår hur kompilatorer fungerar är det som egentligen händer inte så mycket att Lisp har en konstig syntax som att Lisp inte har någon syntax. Man skriver program i de parse-träd som genereras i kompilatorn när andra språk parsas. Men dessa parse trees är fullt tillgängliga för dina program. Du kan skriva program som manipulerar dem. I Lisp kallas dessa program för makron. De är program som skriver program.
Program som skriver program? När skulle du någonsin vilja göra det? Inte särskilt ofta, om man tänker i Cobol. Hela tiden, om man tänker i Lisp. Det skulle vara praktiskt här om jag kunde ge ett exempel på ett kraftfullt makro, och säga där! vad sägs om det? Men om jag gjorde det skulle det bara se ut som rappakalja för någon som inte kan Lisp; det finns inte utrymme här för att förklara allt du behöver veta för att förstå vad det betyder. I Ansi Common Lisp försökte jag gå framåt så fort jag kunde, och trots det kom jag inte till makron förrän på sidan 160.
Men jag tror att jag kan ge ett slags argument som kan vara övertygande. Källkoden till Viaweb-redigeraren bestod förmodligen till 20-25 procent av makroner. Makroer är svårare att skriva än vanliga Lisp-funktioner, och det anses vara dålig stil att använda dem när de inte är nödvändiga. Så varje makro i den koden finns där för att det måste finnas. Det betyder att minst 20-25% av koden i det här programmet gör saker som du inte enkelt kan göra i något annat språk. Hur skeptisk Blub-programmeraren än är till mina påståenden om Lisp’ mystiska krafter borde detta göra honom nyfiken. Vi skrev inte den här koden för vårt eget nöjes skull. Vi var ett litet nystartat företag som programmerade så hårt vi kunde för att sätta tekniska barriärer mellan oss och våra konkurrenter.
En misstänksam person skulle kunna börja undra om det fanns någon korrelation här. En stor del av vår kod gjorde saker som är mycket svåra att göra i andra språk. Den resulterande programvaran gjorde saker som våra konkurrenters programvara inte kunde göra. Kanske fanns det något samband. Jag uppmuntrar dig att följa den tråden. Det kan finnas mer än vad man kan tro om den gamle mannen som haltade på sina kryckor.