Makrók és kvazitsitaty Scala

Nem is olyan régen a kiadás Scala 2.11.0. Egy figyelemre méltó újítása ez a verzió kvazitsitaty - kényelmes mechanizmust leíró mondattan fák Scala keresztül értelmezhető fordításkor vonalak; nyilvánvaló, hogy az első helyen, ez a mechanizmus úgy tervezték, hogy együtt használható makrókat.

Meglepő módon ügyéről, amíg a makró témát Scala nem tekinthető nagyon aktív; last post
egy komoly figyelmet a makro-ben már egy évvel ezelőtt.

Ebben a bejegyzésben lesz szó részletesen írásban egyszerű Macro kialakítva, hogy a JSON deserialization kódot az osztály hierarchia.

Nyilatkozat a problémát

Van egy csodálatos könyvtár dolgozó JSON Scala - spray.json.

Jellemzően érdekében deserialize néhány JSON objektum segítségével ezt a könyvtárat, csak pár import:

Elég egyszerű, nem? És ha azt akarjuk, hogy deserialize az egész osztály hierarchia? Itt egy példa a hierarchia, amely azt fogja vizsgálni a jövőben:

Mint látható, több deserialized osztályok különböző számú érvek különböző örökölt absztrakt szülő. Ez egy természetes vágy, ha deserializing ilyen szervezeteknek -, hogy adjunk egy mezőbe írja be JSON-objektum, és amikor deserializing a tervek szerint ezen a területen. Az ötlet lehet kifejezni a következő pszeudo-kód:

spray.json Könyvtár biztosítja a képességét, hogy a JSON, hogy meghatározza bármilyen felhasználó által megadott szabályok szerint bővül a formázó RootJsonFormat. Úgy hangzik, mint amire szükségünk van. A lényege a jelformáló kell kinéznie:

Ez a kód úgy néz ki, egy kicsit ... sablonos. Ez egy nagy kihívás a makró! A maradék a cikk foglalkozik a fejlesztés a makró, amely generál egy kódot, amely mint egy kiindulási pont csak az üzenet típusát.

projekt szervezet

Az első akadály felé a programozó, hogy dolgozzon makrók, hogy az SBT nem akar fordítani mind a makro- és a saját kódját. Ezt a kérdést a dokumentációban SBT, és azt ajánlom az alábbi megoldásokat.

Meg kell osztani a makro-kód és a fő alkalmazási kódot két projekt, amelyre utalni kell, hogy a projekt / Build.sbt fő fájl. Egy kísérő cikk, ezek a készítmények a már megtörtént kód, amely összeköti a kapott fájlokat:

Tovább finomság, hogy ha szeretné, hogy a makró dolgozni az osztály hierarchia - a hierarchia kell időpontjában ismert a Macro. Ez problémákat okoz, mert szekvencia fájlkezelése a fordító nem mindig nyilvánvaló. A megoldás erre a problémára - vagy van az osztályok, amelyek kell futtatni a makrót egy projekt makró (a közzététel makró továbbra is egy másik projektben), vagy egyszerűen helyezze a osztályok ugyanazt a fájlt, amely készült a Macro.

Amikor a hibakeresés makrók segít a fordító opció -Ymacro-debug-lite. amely lehetővé teszi, hogy megjelenik a konzol a kibontakozó összes makrók a projekt (ezek az eredmények nagyon hasonlóak a Scala kódot, és gyakran változott össze kézzel át a fordító, amely segíthet a hibakeresés nem triviális esetben).

Makrók Scala dolgozni majdnem olyan jól, mint a gondolkodás. Felhívjuk figyelmét, hogy a Scala visszaverődés API jelentősen eltér Java visszaverődés, mivel nem minden Scala fogalom ismert szabványos Java könyvtár.

A mechanizmus a makrók Scala lehetővé teszi, hogy hozzon létre kódrészlet fordításkor. Ezt használja a típusos API, amely létrehozza a szintaxisfa megfelelő kódot, amit szeretne létrehozni. A makrók Scala jelentősen eltér a szokásos C nyelv makrók, így nem szabad összekeverni.

A Scala, a makro környezetének alapján osztályban. Egy ilyen eset történt osztály mindig át a makrót a nyilvánosságra hozatal. Akkor importálni belülről egy tárgy Universe és használja őket ugyanúgy, mint a futási gondolkodás -, hogy találják meg a jellemzőket típusok, módszerek, tulajdonságok, stb Ugyanebben az összefüggésben lehet létrehozni szintaktikai fák segítségével osztályok, mint a szó szerinti. Constant. Sorolja et al.

Valójában a makro - egy függvény, amely elfogadja, és visszatér a szintaktikai fák. Írjunk egy sablont Makrogazdaságunk:

Macro parseMessage [T] T. kap típus, amelyet a bázis egy hierarchia osztályok deserialized, és a szintaxis fa előállításához deserialized típusú térkép objektumot. és visszaad egy szintaxisfa termelni deserialized tárgy, öntött a bázis típusú T.

T argumentumtípus ismertetett különleges módon: azt jelzi, hogy a fordító is alkalmazni kell, akkor hallgatólagosan generált objektum típus c.WeakTypeTag. Általánosságban elmondható, hogy TypeTag implicit argumentum használt Scala dolgozni generikus típusok, az érvek általában nem állnak rendelkezésre futási idő miatt írja törlést. Mert érvek makró fordító használatát igényli nemcsak TypeTag. és WeakTypeTag. hogy jól értem, van kötve a sajátosságok a fordító (nem rendelkezik „teljes» TypeTag típus, amely még nem lehet teljesen során keletkező Macro). Típus kapcsolatos TypeTag. lehet eljárással előállított typeof [T] Object Universe; rendre WeakTypeTag létezik weakTypeOf módszer [T].

Az egyik hátránya a makro leírása nem nyilvánvalóságát szintaxis fák. Például kódrészlet 2 + 2 generáló kell kinéznie Apply (Válassza (szó (Constant (2) bekezdése), TermName ( "$ plusz")), List (szó (Constant (2)))); Még súlyosabb esetekben merül fel, amikor azt kell elképzelni, hogy a nagyobb mennyiségű kódot a helyettesítő mintát. Természetesen ez a komplexitás nem tetszik nekünk, és mi lesz legyőzni azt.

Kvazitsitaty

A fent említett hiánya makrók óta Scala 2.11.0 verzió könnyen megoldható a segítségével kvazitsitat. Például, a fenti szerkezet, amely leírja az expressziós 2 + 2 formájában kvazitsitaty éppen olyan lesz mint q „2 + 2”. ami nagyon kényelmes. Összességében kvazitsitaty Scala - egy sor húr interpolátorok, amely található a tárgy Univerzumban. Az importálás után ezek interpolátorok az aktuális feladatot, akkor ez lehet használni egy sor karaktert egy szövegben, amely meghatározza a fordító saját feldolgozás. Különösen, a végrehajtás a probléma jöhet a interpolátorok pq minták, CQ, hogy megfeleljen kifejezések ágak. és q a teljes kifejezést nyelvet.

Ami a többi húr interpolátorok Scala nyelvén kvazitsitat lehet hivatkozni változók környező körét. Például, akkor hozza létre a kifejezést 2 + 2, az alábbi kód:

Interpoláció előfordulhatnak különböző módon különböző típusú változókat. Például a string típusú változók fák létrehozott string állandók. Utalni egy változó nevét, akkor létre kell hozni TermName objektumot.

Mint látható a példa a generált kódot rendelnek az elején, meg kell tudni, hogy létrehoz a következő elemeket tartalmazza:

  • egyezik a változó TypeName ágak esetében. mindegyikének megfelelő típusú hierarchia;
  • minden ága - átadása a lista a megfelelő osztály konstruktora argumentumneveket map.getFields eljárás;
  • ugyanazon a helyen - a dekonstrukciója a kapott szekvencia (ugyanazt a kifejezést mérkőzés) a változók és átadása ezeket a változókat egy típusú kivitelező.

Először is, úgy a generáció egy közös fába minden mérkőzés kifejezést. Úgy kell használni interpoláció változók keretében kvazitsitaty:

Ebben a kód használt rész egy speciális típusú interpoláció. Expression ügyben. $ Match kikötések blokkon belül kerül bemutatásra, mint egy listát az ügy ágak. Ahogy emlékszem, minden ág a következő legyen:

Egy ilyen kvazitsitaty ág felírható a következőképpen:

Ez kódrészlet több kvazitsitat: kifejezés pq „$ name” hoz létre, minták, amelyek tovább helyettesített szekvencia kifejezése (.). Mindegyik kifejezésekhez írja JsValue. hogy átalakíthatjuk a megfelelő típusú, mielőtt azt a kivitelező; használja kvazitsitata generáló hívás convertTo módszer. Megjegyezzük, hogy ez a módszer rekurzív hívja formázó, ha szükséges (lehetséges, hogy olyan tárgyakat, mint a Message egymást.

Végül a kapott szintaxisfa álló kifejezést meccset generált esetünkben ágak is kialakítható segítségével interpoláció:

Ez a fa épül a fordítóprogram a használat helyén a makró.

A teljes időszak alatt a technológiák fejlődését, metaprogramozás egyre fontosabb eleme a programozási nyelvek, gyakrabban használják a mindennapi kód végrehajtására különböző fogalmak. Scala Scala makrók releváns eszköz, amely képes megmenteni minket egy másik rutin munka, hogy a JVM világ előtt úgy döntöttek, hogy észre a reflexió vagy kódot generáció.

Természetesen a makro - ez egy hatékony eszköz, amely óvatosan kell alkalmazni, ha nem megfelelően használt, csak annyi, hogy lőni magát a láb, és esik a mélységbe a támogatott kódot. De mindig érdemes kipróbálni, hogy automatizálják rutin műveletek, és ha a makrók lehet segítségünkre ebben a feladatban - akkor kell használni, és a közösség javát.

használt anyagok