metaprogramazioa
Zer da metaprogramatzea? hemen azalpen luze eta zabala. Laburbilduz: normalean, programa batek datuak prozesatzen ditu eta horren emaitza itzultzen du. Metaprogramazioan, programa batek bertze programa bat (baita bere ‘burua’ ere) manipulatzeko gaitasuna du.
Macro
Macro hitzak erranahi anitz izan ditzake:
- C/C++ lengoaian macro bat funtzio baten ‘alias’ bat baino ez da. Hau da, konpilazio garaian ‘alias’ hori ageri den lekuan funtzioa txertatuko da.
- Microsoft Excel programan, bertako datuak manipulatzeko programa bat da.
- …
Haxe lengoaian, konpilazio garaian exekutatzen diren programak dira. Haxe lengoaia bera erabiliz nahi duguna egiteko. Macroek izugarrizko boterea dute, hauek dira egiten ahal diren gauzen adibide batzuk:
- Kodea sortu/aldatu/ezabatu (klaseak, funtzioak, aldagaiak… edozer gauza).
- Helburu kodean konpilazio uneko informazioa gorde (Git mezua, data, ordenagailuaren informazioa…).
- Lengoaian berez existitzen ez diren adierazpenak onartu. Konpilazio garaian interpretatu eta lengoaiak berez onartzen dituen modura itzultzeko.
- Helburu kodean kanpoko fitxategietako datuak txertatu. Konfigurazio fitxategi handiak, adibidez.
- Konpilazio garaiko enkriptazioa.
- SQL, XML, JSON edo bertze edozein sintaxi konpilazio garaian egiaztatu (errore zehatzak identifikatuz)
Irudi honetan ikus daiteke konpilazioko zein fasetan exekutatzen diren macroak:
Hiru macro mota daude Haxen: Hasieratze macroak (initialization macros
), adierazpen macroak (expression macros
) eta eraikitze macroak (build macros
).
Hasieratze macroak (‘initialization macros’)
Programa konpilatzeko garaian exekutatuko diren funtzioak dira. Adibidez, helburu plataformaren arabera (Windows, Mac, web, Android…) dagozkien fitxategiak (irudi, audio…) karpeta batetik bertzera mugitzea eta tamainak automatikoki aldatzea edo dena delakoa. Funtzio honetan zein plataformarako konpilatzen ari garen detektatu eta horren araberako exekuzioak burutuko dira.
1 | --macro Macroak.fitxategiak_kopiatu() |
Adierazpen macroak (‘expression macros’)
Macro hauek C lengoaiako #define
edo macro preprozesatzaileak
bezala funtzionatzen dute. Funtzio itxura dute, baino macro
hitzarekin definituko dira: static public macro function sortze_data()
. Funtzio hauek konpilazio garaian exekutatu eta une horretan lortutako informazioa txertatuko dute deitu zaien puntuan. Bukaerako kodean funtzioaren arrastorik utzi gabe. Adierazpenak kontsumitu eta adierazpenak itzultzen dituzte.
Honen erabilpen praktiko bat programaren konpilazioa noiz izan zen edo une horretan Git-eko azken commit mezua zein zen txertatzeko balio du. Adibidez,
1 | class Macroak { |
1 | class Main { |
Kode honen bidez sortutako JS kodea horrelako zerbait izanen da.
1 | ... |
Eraikitze macroak (‘build macros’)
Demagun HTML fitxategi bateko id
guztiak txukun-txukun izan nahi ditugula klase batean eskuragarri, kode osaketarekin guztiak erraz atzitzeko. Id guztiak eskuz kopiatu eta Id
izeneko klase batean aldagai pila bat sortzen ahal ditugu. Zer gertatuko da HTML fitxategia aldatzen badugu? id
guztiak berriro kopiatu behar ditugu? Ezin da hori nola edo hala automatizatu? Hemen sartzen dira eraikitze macroak eta magia beltza!!
Macro mota hau konpilazioan programako elementuak (klaseak, interfazeak, enum…) eraikitzen diren unean exekutatuko da, sintaxi zuhaitz abstrakua (Abstract Syntax Tree
edo AST
) definitzean. Honela egiten zaio dei macro mota honi:
1 | @:build(Macroak.eraiki_id('index.html')) |
Haxek kode osaketa eskeintzen duela aipatu dut. Kode osaketa hori ahalbidetzeko, kodea idazten ari garela (
edo .
sakatzean, konpilatzailea martxan jarri eta funtzioak ((
idaztean) behar dituen parametroak edo aldagaiak (.
idaztean) eskeintzen dituen funtzio edota propietateak itzultzen ditu, hurrenez hurren.
Goiko adibideari jarraiki, Id.
idaztean (gogoratu .
idaztean konpilatzailea martxan hasiko dela), Macroak.eraiki_id
funtzioari deituko zaio. Funtzio horren bidez:
index.html
fitxategia irakurri- fitxategian ageri diren
id
guztiak identifikatu eta gorde - array horretako
id
bakoitzeko,Id
klasean String motako propietate bat gehituko dugu, hemen kodea:
1 | // funtzio honek 'Id' klaseak izanen dituen eremuak (Field) itzuliko ditu array batean |
Modu honetan, HTML fitxategiko identifikadoren bakoitzeko Id
klasean aldagai bat sortu dugu, horrela geldituko litzateke klasea:
1 | class Id { |
Honela, identifikatzaile guztiak automatikoki agertuko zaizkigu, ez ditugu gogoratu beharko eta idazterakoan ez dugu hutsik eginen. Gainera, kodean erreferentziatzen dugun HTML-ko id
ren bat aldatzen bada, konpilazioan errorea emanen digu, Id
klasean ez delako egonen lehendik dei egin diogun id
hori.
Hemen erabileraren adibide bat:
1 | // JavaScript-eko 'jQuery' edo '$'-ren baliokidea da 'J' |
Garapen pixko bat gehiagorekin, klaseak eta etikeak ere modu honetan parseatu ditut eta eduki mota abstraktuen bidez, jQuery deiak errazago egin ditut.
Hemen kodea eta funtzionamenduaren GIF bat: