Metaprogramozás
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 karakterláncokból állítják össze, de másként is létrehozható paraméterekből és környezetből, mint például JavaScript.[* 1] Í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.[5] 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.[7]
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 csak 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]- Scheme higiénikus makrók
- MacroML
- Template Haskell
- Scala makrók
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 tartalmaznak a következők:
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]- ASF+SDF Meta Environment
- DMS Software Reengineering Toolkit
- Joose (JavaScript)
- JetBrains MPS
- Moose (Perl)
- Nemerle
- Rascal Metaprogramming Language
- Stratego/XT
- Template Haskell
Megjegyzések
[szerkesztés]Hivatkozások
[szerkesztés]- ↑ Harald Sondergaard: Course on Program Analysis and Transformation. (Hozzáférés: 2014. szeptember 18.)
- ↑ Generative Programming (2000. november 4.). ISBN 0-201-30977-7
- ↑ The Art of Metaprogrmming in Java. New Circle . [2017. február 14-i dátummal az eredetiből archiválva]. (Hozzáférés: 2014. január 28.)
- ↑ Programming Concepts: Type Introspection and Reflection. The Societa . (Hozzáférés: 2014. szeptember 14.)
- ↑ a b What Is Metaprogramming? – Part 2/2. Perpetual Enigma . (Hozzáférés: 2014. augusztus 14.)
- ↑ Rdoc for Class: BasicObject (Ruby 1.9.3) - instance_eval. (Hozzáférés: 2011. december 30.)
- ↑ Art of Metaprogramming
- ↑ IOCCC 1994 Worst Abuse of the Rules. [2017. május 3-i dátummal az eredetiből archiválva]. (Hozzáférés: 2017. május 2.)
- ↑ The challenge of metaprogramming. IanBicking.org . (Hozzáférés: 2016. szeptember 21.)
- ↑ Beware of Metaprogramming. Medium.com . Medium Corportation. (Hozzáférés: 2014. augusztus 21.)
- ↑ 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: 2012. augusztus 29.)
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. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.