Metaprogramozás

A Wikipédiából, a szabad enciklopédiából

A metaprogramozás egy programozási módszer, amiben a számítógépes programok adatokként kezelnek programokat. Ez azt jelenti, hogy a program olvas, generál, elemez, transzformál egy másik programot, vagy futás közben módosítja önmagát.[1][2] Bizonyos esetekben ez lehetővé teszi, hogy a forráskód rövidebb legyen, ami lerövidítheti a fejlesztés idejét.[3] Néha ez utóbbi fordítva van, de a program rugalmasabbá válik abban, hogy újrafordítás nélkül is kezeljen új helyzeteket.

Használható arra is, hogy egyes számításokat a futásidőből áttegye fordítási időbe, és saját magát módosító kódot hoz létre. A nyelv, amin metaprogramozást végeznek, metanyelv. A manipulált program nyelve a tárgynyelv. A reflexió a programnyelvnek az a képessége, hogy önmaga metanyelve legyen.[4] A reflexió értékes eszköz a metaprogramozás támogatására.

Megközelítések[szerkesztés]

A metaprogramozás lehetővé teszi generikus kód fejlesztését. Nagyon hasznos, ha a nyelv képes első osztályú adattípusként kezelni saját magát, mint a Lisp, Prolog, SNOBOL, vagy Rebol nyelvek. A generikus programozás lehetővé teszi, hogy úgy lehessen kódolni, hogy nem specifikáljuk előre, hogy az milyen típusra vonatkozik, mivel azokat paraméterként fogják helyettesíteni használatkor.

Többnyire a következő módok valamelyike áll a metaprogramozás mögött:[5]

  • Futásidőben elérhető a futtató környezet belseje a futtatott kódból egy API-n keresztül. Ilyen a .NET IL kibocsátó.
  • Programkódot tartalmazó kifejezések dinamikus végrehajtása. A kódot gyakran stringekből állítják össze, de másként is létrehozható paraméterekből és környezetből, mint például Javascript.[6] Így program ír programot.

Habár a legtöbb nyelv mindkét módszert lehetővé teszi, többnyire elmennek az egyik vagy a másik irányba.

A harmadik megközelítés szerint a nyelvet teljesen kívülről nézik.[7] Az általános célú programtranszformációs rendszerek a generikus metaprogramozás közvetlen implementációi, például azok a fordítók, amelyek fogadják a nyelv leírását, és bármely transzformációt elvégeznek ezeken a nyelveken. Ez lehetővé teszi, hogy bármely célnyelvre alkalmazható legyen a metaprogramozás, függetlenül attól, hogy vannak-e eszközök, amelyekkel az adott nyelven metaprogramozást lehet végezni. Ezt láthatjuk működni a Scheme programozási nyelvvel, valamint azzal, hogyan lehet túllépni a C korlátain a Scheme nyelv szerkezeteinek segítségével.Art of Metaprogramming

Példák[szerkesztés]

Egy egyszerű példa ez a shell szkript, ami a generatív programozás egy példája:

#!/bin/sh
# metaprogram
echo '#!/bin/sh' >program
for I in $(seq 992)
do
        echo "echo $I" >> program
done
chmod +x program

A szkript egy 993 soros programot hoz létre, ami kiírja a számokat 1-től 992-ig. Ez ugyan nem hatékony módszer, csak bemutatja, hogyan lehet kódot generálni. Viszont a programozó egy perc alatt megírhatja, ezzel ennyi idő alatt 1000 sort generálva.

A quine egy speciális metaprogram, ami önmagát hozza létre. Egyes nyelvekben az üres program érvényes program, ezért ez a legkisebb quine az ilyen nyelveken. Ezek a programok csak tudományos jelentőséggel bírnak. 1994-ben az üres program nyerte el A legrosszabb visszaélés a szabályokkal díjat az International Obfuscated C Code Contest (IOCCC) versenyen.[8]

Nem minden metaprogram használ generikusságot. A futásidejű önmódosítás vagy az inkrementális fordítás lehetősége is felhasználható anélkül, hogy aktuálisan forráskódot generálnának. Ezeket is sok nyelv támogatja, mint C#, Forth, Frink, Groovy, JavaScript, Lisp, Lua, Perl, PHP, Python, REBOL, Ruby, Smalltalk, és Tcl.

A metaprogramozásra a Lisp nyújtja a legtöbb lehetőséget. Az unquote operátor (tipikusan a vessző) által bevezetett programszakasz definiálási időben hajtódik végre. Így a metaprogramozás nyelve ugyanaz, mint a gazdanyelv, és már létező Lisp rutinok közvetlenül használhatók metaprogramozáshoz. Más programnyelvek ezt egy értelmező beépítésével oldják meg, ami közvetlenül a program adatait elemzi. Néhány gyakran használt nyelv számára vannak ilyen implementációk, például a RemObject Pascal Scriptje az Object Pascal számára.

A metaprogramozás egy megközelítése a beágyazott nyelvek (DSL) használata. A lex és a yacc a generikus metaprogramozást szolgálja, és lexikai elemzőket és parsereket generálnak. A felhasználónak cssak a megfelelő szabályos kifejezéseket és környezetfüggetlen nyelvtanokat kell megírnia, meg a nyelv hatékony parszolását végző algoritmusokat implementálnia.

Támogatás és kihívások[szerkesztés]

A metaprogramozás haszna az, hogy felgyorsíthatja a fejlesztést, és növeli azoknak a programozóknak a teljesítményét, akik megtanulták és begyakorolták. Néhány elemzés szerint meredek a tanulási görbe, ameddig a fejlesztő megtanulja a metaprogramozás teljes eszközkészletét, és felgyorsul.[9] Mivel nagyobb hatékonyságot és rugalmasságot ad futásidőben, hibás használata vagy a vele való visszaélés váratlan hibákat eredményezhet mindenféle figyelmeztetés nélkül, amelyeket nehezebb észrevenni és javítani. Ha nem elég körültekintően használják, akkor sérülékenyebbé teszi a rendszert. Ezek egy részét egy megfelelő fordító meg tudná előzni, ha legalább figyelmeztet a hiányzó paraméterekre, az érvénytelen vagy inkorrekt adatokra, amelyek a kívánttól eltérő eredményeket vagy ismeretlen típusú kivételeket okozhatnak.[10] Éppen ezért egyes kritikusok szerint csak képzett és tapasztalt programozóknak lenne szabad megengedni azt, hogy metaprogramozást támogató eszközöket hozzanak létre egy nyelvhez vagy környezethez, és a többi programozónak először egy konvenció részeként kell megtanulnia, hogyan bánjon velük.

Felhasználása különböző nyelvekben[szerkesztés]

Makrórendszerek[szerkesztés]

Makró assemblerek[szerkesztés]

Az IBM/360 és továbbfejlesztései fejlett makró assembler lehetőségekkel bírtak, amelyeket gyakran használtak arra, hogy egész Assembly programokat generáljanak [forrás?] vagy programszakaszokat hozzanak létre például különböző operációs rendszerek számára. A CICS tranzakciófeldolgozó rendszer assembler makrói COBOL utasításokat generáltak előfeldolgozó lépésként.

Más assemblerek, például az MASM, is támogatnak makrókat.

Metaosztályok[szerkesztés]

Metaosztályokat tarttalmaznak a követj:

Template metaprogramozás[szerkesztés]

Staged metaprogramozás[szerkesztés]

Függő típusokkal[szerkesztés]

  • A függő típusok használata kizárja, hogy érvénytelen kód jöjjön létre.[11] Azonban ez a megközelítés bleeding-edge, és ritkán lehet vele találkozni a kutatási célokra készült nyelveken kívül.

Implementációk[szerkesztés]

Fordítás[szerkesztés]

Ez a szócikk részben vagy egészben a Metaprogramming című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel.

Jegyzetek[szerkesztés]

  1. Harald Sondergaard: Course on Program Analysis and Transformation. (Hozzáférés: 2014. szeptember 18.)
  2. Generative Programming (2000. november 22.). ISBN 0-201-30977-7 
  3. The Art of Metaprogrmming in Java. (Hozzáférés: 2014. január 28.)
  4. Programming Concepts: Type Introspection and Reflection. (Hozzáférés: 2014. szeptember 14.)
  5. What Is Metaprogramming? – Part 2/2. (Hozzáférés: 2014. augusztus 14.)
  6. for example, instance_eval in Ruby takes a string or an anonymous function. Rdoc for Class: BasicObject (Ruby 1.9.3) - instance_eval. (Hozzáférés: 2011. december 30.)
  7. What Is Metaprogramming? – Part 2/2. (Hozzáférés: 2014. augusztus 14.)
  8. IOCCC 1994 Worst Abuse of the Rules
  9. The challenge of metaprogramming. (Hozzáférés: 2016. szeptember 21.)
  10. Beware of Metaprogramming. Medium Corportation. (Hozzáférés: 2014. augusztus 21.)
  11. Chlipala, Adam (2010. június 1.). „Ur: statically-typed metaprogramming with type-level record computation”. ACM SIGPLAN Notices 45 (6), 122–133. o. DOI:10.1145/1809028.1806612. (Hozzáférés ideje: 2012. augusztus 29.)