Az ERLANG programozási nyelv

Bevezetés

Bevezetés

Erlangban két lehetoség is van grafikus alkalmazások készítésére, az egyik a GS, a másik a wx. A fejlesztok a wx használatát javasolják, mivel a GS-t tervezik kivenni a nyelvbol.

GS

A GS (Graphic System) egy általános grafikus interfész az Erlanghoz. Használatát tervezik megszüntetni az Erlang 15-ös verziójától. Fejlesztésekor két alapelvet követtek: - legyen egy grafikus rendszer, amelyet könnyen meg lehet tanulni - a rendszer legyen hordozható különbözo platformokra A GS egy általános, minden platformon futó API-t használ. A grafikus rendszer alapja a grafikus objektum. Az objektumok hierarchikusan épülnek fel, mindegyiknek van szüloje. A leggyakrabban használt objektumok: window, button, label, listbox, frame. Az objektumok létrejöttükkor kapnak egy egyedi azonosítót, amellyel lehetoség van az objektum megjelenésének és muködésének konfigurálására. A konfigurálás az Options tulajdonság segítségével történik. A legtöbb option rendelkezhet típussal és értékkel. Amikor egy Erlang processz létrehoz egy grafikus objektumot, akkor a processz fogja birtokolni az objektumot. A grafikus rendszer megjegyzi az objektumokat birtokló processzeket, mert az bejövo eseményeket az objektumot birtokló processzhez továbbítja, illetve a processz megszunése esetén megsemmisíti a grafikus objektumot. Az események lényegében üzenetek, amelyeket a grafikus objektumok küldenek az oket birtokló processzeknek. A processzet információt kap például arról, hogy a felhasználó egy gombra klikkelt, mozgatott egy ablakot vagy egyéb eseményt váltott ki.

A GS használatához fontos függvények

- gs:start(). Elindítja a grafikus szervert és visszaadja az objektum azonosítóját. Ha már el volt indítva, akkor csak visszaadja az azonosítóját. - gs: stop(). Megállítja a grafikus szervert és bezár minden egyes ablakot, amelyet a grafikus szerver létrehozott. A stop nem ellentettje a startnak, mert a stop hatására minden egyes grafikus szerver megáll és megszunnek az objektumaik. - gs:create(Objtype, Parent, Options). Létrehoz egy új objektumot a megadott Objtype típussal, megadott Parent szülovel és konfigurálja az objektumot a megadott Options jellemzokkel, majd visszaadja az objektum azonosítóját, vagy hiba esetén egy {error, Reason} párt. - gs:create(Objtype, Name, Parent, Options). Muködése hasonló a három paraméteres create fügvénnyel, azzal a különbséggel, hogy a Name paraméterben megadott névvel lehet majd az objektumra hivatkozni. A névnek atomnak kell lennie. - gs:destroy(IdOrName). Megsemmisíti az azonosító vagy név alapján megadott objektumot és az összes gyerekét. - gs:config(IdOrName, Options). A megadott jellemzokkel konfigurálja az azonosítóval vagy névvel megadott objektumot. Ok-val tér vissza, ha sikeres volt a konfigurálás, {erros, Reason} párral, ha nem volt sikeres. - gs:read(IdOrName, OptionKey). Megadja az azonosítóval vagy névvel megadott objektumnak a megadott jellemzojét. Visszatér a jellemzo értékével, ha sikeres volt, illetve {error, Reason} párral, sikertelenség esetén. Az egyszeruség kedvéért használhatóak a függvények paraméterként is, pl gs:window(gs:start(), {map, true}). Az objektumoknak nevet adhatunk létrehozáskor (create), a név egy egyedi atom kell legyen, amely referenciaként muködik. Ezeket nevesített objektumoknak nevezzük. Ennek elonye a kódban a jobb átláthatóság és könnyebb használat, mivel nem azonosítókat kell megjegyezni. Az objektumok nevei lokálisan a processzeken belül, amelyek létrehozzák azokat. Azaz, a név csak egy processzre érvényes, így különbözo processzekben hasznaálhatjuk ugyanazt a nevet különbözo objektumokra. Abban az esetben, ha a processzek között használunk referenciákat, akkor a nevek helyett azonosítókkal azonosítja a GS az objektumokat. Szükség esetén az id optionnel le lehet kérdezni az objektum azonosítóját. Elosztott Erlangban óvatosan kell bánni a nevekkel, ezeket {Name, Node} formában szokáso megadni, a Node azt mondja meg, hogy milyen node-on keletkezett az objektum.

Option-ok

Minden egyes objektum tartalmaz egy halmazt, amelyben fel vannak sorolva a jellemzoi. Ezek kulcs-érték párok, a kulcsok pedig atomok kell legyenek. Jellemzotol függoen az érték lehet Erlang term is. Gyakori jellemzok például: x, y koordináták, magasság, hossz, szöveg, szín. A jellemzok megadhatók az objektumok létrehozásakor is egy listában, pl.: Butt = gs:create(button,Win, [{x,10},{y,10}]) egy gomb, amely a (10,10)-es pozíción van. A megadott jellemzok kiértékelési sorrendje nem definiált. Minden objektum leírható termekkel a jellemzoibol. Ezeket besorolhatóak egy táblázatba, amelyek a következo a fejléce: {Option, Érték}, Alapérték, Leírás. Az alapérték lehet értéku, ami azt jelenti, hogy a gs vagy a back-end állítja be az értéket. Többféle optiont különböztetünk meg: config-only, illetve read-only. A config-only jellezok értéke megváltoztatható, míg a read-only jellemzok csak lekérdezhetoek. Minden objektumok rendelkeznek típussal.

Események

Az események valójában üzenetek, amelyeket a birtokló processz kap meg valamilyen felhasználói interakció után. Például, ha a felhasználó megklikkelt egy gombot, akkor a gombot gombot létrehozó processz kap róla egy üzenetet. Az objektumokra engedélyezni kell a különbözo eseményeket, például egy klikk esemény engedélyezése a {click, true} jellemzo beállításával történik. Az események engedélyezése után a birtokló processz meg fogja kapni az eseményeket. Az esemény egy ötös, amely tartalmazza a {gs, IdOrName, EventType, Data, Args} információkat. A gs megadja, hogy melyik grafikus szervertol jött az esemény, az IdOrName megadja az objektumnak az azonosítóját vagy nevét, amelyen esemény történt, EventType az esemény típusa (pl. click), A Data részbe tetszoleges Erlang term írható, amely az üzenet része lesz, az Args pedig specifikus információkat tartalmaz (pl. egy motion esemény bekövetkezésekor tartalmazhatja az x és y koordinátát). Két különbözo eseménytípust különböztet meg a GS: a generikus eseményt és az objektumspecifikus eseményt. A generikus események minden típusú objektumra ugyanúgy muködnek, a grafikus szerver mindig ugyanazt az információt küldi a processznek. Ezek a következok: buttonpress, buttonrelease, enter, focus, keypress, leave, motion. A buttonpress és buttonrelease események akkor generálódnak, amikor egy objektum belsejében egérgombnyomás történt. Az enter és leave események akkor generálódnak, amikor egérrel egy objektum felé megy a felhasználó vagy elmegy egy objektumról. A focus esemény esetében a billentyuzetrol megszunik a fókusz. Keypress esetében valamilyen szöveget ír a felhasználó az objektumba. Motion esetében pedig azt érzékeli, hogy az objektum egérrel történo mozgatása történt. Objektumspecifikus események esetében különbözo objektumokra különbözo végrehajtásra van szükség. Ilyenek a click és doubleclick események. A programban az eseményeket a le kell kezelni, ehhez az eseményfogadónak meg kell adni a megfelelo azonosítókat egy eseménykezelo ciklusban. Másik módszer, hogy az objektumok létrehozásakor nevet adunk az objektumoknak, majd ezzel a névvel hivatkozunk az objektumokra az eseménykezeloben. Harmadik megoldás az, hogy az események data részében eltárolunk valamilyen információt, ami segít az azonosításban.

Packer

Egyes események eredményét, mint például egy ablak méretének a megváltoztatását a Packer, más néven geometry manager végzi. GS-ben a packer funkcionalitása a frame típusú objektum tulajdonsága. A packer tulajdonság a frame-mel együtt végzi a gyerek objektumok méretének és pozíciójának megváltoztatását. A packer frame rendezi el a gyerek objektumokat egy gridben megfelelo sorokban és oszlopokban. Minden sornak és oszlopnak van egy kiterjedés (streching) tulajdonsága, lehetséges a sorok nyújtása, illetve a fix méretuvé beállítása is. Ez a grid láthatatlan a felhasználó számára.

A wx

Erlangban wx segítségével is létrehozhatóak a grafikus alkalmazások. A wx újabb a GS-nél, s az Erlang inkább a wx használatát javasolja a felhasználóknak. A wx egy alkalmazás, amely egy Erlang kötés a wxWidgetekre. A wxWidget egy objektumorientált C++ api. Az Erlang egy-egy mappelést hasznal a wxWidgetekre. A wx egy interfész, ami több modulba van osztva, minden modulnév wx-szel kezdodik. Ezek a modulok tartalmazzák a grafikus felület megvalósításához szükséges függvényeket. Az objektumokat és objektum referenciákat wx-ben processzeknek tekintjük, mintsem termeknek. Amikor az objektumokon operálunk, az objektumok állapotot válthatnak, nem muködnek funkcionális objektumokként, mint a termek. Minden objektumnak van típusa, s az adott objektumot a megfelelo Erlang modul tud kezelni vagy az alosztályai. Típusellenozés történik elobb, így garantált, hogy csak a modul csak az objektumon vagy az örökölt osztályokból származó objektumokon kerül használatba. Például a wxWindow C++ osztály a wxWindow Erlang modulban van implementálva, a tagjai pedig wxWindow:függvény formában hívható meg, pl. wxWindow::CenterOnParent. Alapvetoen az Erlang api megegyezik az eredetivel, de akad néhány kivétel, pl. a C++-ban használt tömbök az Erlangban listákkal vannak reprezentálva, idonként párral. A színeket a {Piros, Zöld, Kék [,Alfa]} párral reprezentálja, az Alfa értéke opcionális amikor argumentumot adunk a függvényeknek, viszont visszatérési értékben mindig szerepel. A define-ok, felsorolások és globális változók a wx.hrl fájlban szerepelnek. A define-ok nagy része konstans, de nem mindegyik. Nagyrészük platformfüggetlen, a globális változók példányosítása futásidoben történik meg, amirol a driver gondoskodik egy függvényhívással. A lokális felsorolások prefixe lesz az osztály neve. Ezen kívül néhány globális függvény, mint például a nem osztálybeli metódusok, a wx_misc modulban találhatóak. A wxErlang egy esetleges párhuzamosított drivertként van megvalósítva, azzal a hátránnyal, hogy egy programozói hiba esetén az emulátor muködése abbamarad. Párhuzamosított driver esetében szükség van egy olyan emulatorra, ami képes szábiztosan kezelni a drivert interfészét. wx-ben a wx:new() függvénnyel hozhatunk létre új objektumokat és a wx:destroy() függvénnyel lehet megsemmisíteni. Minden wx:new() függvényhívás után a gui létrehoz egy környezetet és a hozzá szükséges memória mappelést. A létrehozott környezetet meg kell osztani a processzek között, ha a wx-et több processzbol szeretnénk használni. Az aktív környezetet le lehet kérdezni a get_env()¬ nevu függvénnyel, illetve a set_env(Env) nevu függvénnyel be lehet állítani az Env környezetet a processznek. Ha két különbözo processz is meghívja a wx:new() függvényt, akkor nem fognak hozzáférni egymás objektumaihoz, csak a sajátokhoz. A wx:destroy() megívásakor vagy, ha minden processz az alkalmazásban meghalt, a memóriából törlodik a tartalom ls minden az alkalmazás által létrehozott ablak bezáródik. A wx nem töröl és nem használ garbage collectort sem, amíg a program fut. Az objektumok nagy része törlodik, amikor a felhasználó bezárja az ablakot. Ekkor minden objektum megszunik, aminek nem null az ose. A wx:destroy() használatával növelhetjük a szabad memóriát. Ez különösen akkor fontos, ha a programozó a stacken létrehoz objektumokat. Dialógusablakok esetében csak a dialógusablak aktív mindaddig, amíg be nem zárják.

Eseményvezérlés

Erlangban az eseménykezelés eltér az eredeti apitól. A programozó meg kell határozza, hogy milyen eseményeket akar lekezelni. Eldöntheto, hogy a kapott eseményeket üzenetként vagy callback függvényként akarjuk lekezelni. Az eseményekre való feliratkozás egy dinamikus eseménykezelo kapcsolat. Az eseményekre fel kell iratkozni egy bizonyos objektummal egy id vagy egy lehetséges id-kat tartalmazó intervallummal. A callback függvény használata opcionális, ha az esemény nem tartozéka az objektumnak. Így az eseménykezelo is callback függvény vagy egy processz lesz, ami fogadni fogja az esemény üzeneteit. Az események végrehajtásának sorrendje lentrol felfelé történik a widgetek hierachiájában, az utoljára feliratkozott eseménykezelo részérol eloször. A wxEvent:skip() fügvénnyel továbbdobható az esemény, s az adott objektum nem fogja lekezelni, hanem továbbadódik egy vagy több processznek. A legtöbb eseménynek van alap eseménykezeloje. Az események szerkezete a következo: #wx{id = integer(), obj = wx:wxObject(), userData = term(), event = Rec}. Az id az eseményt fogadó objektum azonosítóját jelenti. Az obj mezo tartalmazza az objektumot, amire kapcsoltuk az eseményt. A useData mezo a felhasználó által meghatározott termet, ez az eseményre való feliratkozás tulajdonsága. Az event mezo tartalmazz egy rekordot az esemény típusával. Az eseményrekord elso eleme mindig az a típus, amivel feliratkoztunk az eseményre. Abban az esetben, ha az adott objektumon nem akarjuk lekezelni az eseményt használni kell a wx:skip() függvényt. Ugyanez megvalósítható callback függvénnyel is. A skip tulajdonság beállítható az eseményre való feliratkozáskor. Alapértéke hamis. Az igaz azt jelenti, hogy az objektum megkapja az üzenetet, de nem akarja lekezelni, hanem továbbadja. Dinamikus is meg lehet ezt adni a wxEvent:skip() meghívásával. A callback események le lehet kezelni egy 2 parammaméteres fun callback függvénnyel is, amit akkor kell megadni, amikor az objektumhoz kapcsoljuk az esemenykezelot. A fun két paramétert vár,az elsot leírja az esemény szövege, a második pedig egy referencia az aktuális objektumra, amire meghívódott az esemény. Az eseményobjektum elérheti az összes adatot. Az eseményobjektum törlodik miután a fun függvény visszatér. A callback függvényt mindig más processz hívja meg és kizárólagosan használja a gui-t. Egy callback függvényben levo másik processz hívása holtpontot okozhat a rendszerben, ha a meghívott processz a gui-ra vár.

Fontosabb függvények

- wx:new(). Elindítja a wx szervert, visszaad egy wx_object()-et. - wx:new(Option::[Option]). Ugyanaz, mint a 0 paraméteres, csak az Option-ban megadható a tulajdonsága: debug vagy level. - wx:destroy(). Leállítja a wx szervert. - wx:get_env(). Visszaadja a processznek beállított környezetet. A visszakapott környezet megadható más processznek, így tudnak ugyanabban a környezetben futni. - wx:set_end(Wx_env::wx_env()). Beállítja a paraméterben megkapott környezetet a processznek. - wx:null(). Null objektumot ad vissza. - wx:is_null(Wx_ref::wx_object()). Visszaadja, hogy az adott objektum null-e. - wx:getObjectType(Wx_ref::wx_object()). Visszaadja az objektum típusát. - wx:demo(). Elindítja az Erlang demo programját, ha a mappa létezik és le van fordítva.

Feladat

A program indítását követoen megjelenik 2 lista és két gomb. A menübol történo kiválasztás után az adatok megjelennek a bal oldali listában. A listában tetszoleges egy elem kiválasztható, majd a gombok segítségével átteheto a másik listába. A program indításkor létrehoz adatbázisokat, amiket feltölt elemekkel, majd adatbázisból olvassa ki a listában megjelenítendo elemeket.

Szerzo

Ginál Eszter

Készítés éve

2012

Fejlesztokörnyezet

A program futtatásához az Erlang shellre van szükség, ennek segítségével történik a fordítás. A program egyszeru szövegszerkesztoben készült. A program futtatásához szükséges lépések: - az Erlang shell elindítása - a program path beállítás, ez esetben a forrásfájl a D:/Programok mappában található: cd("D:/Programok"). paranccsal - fordítás, ha pelda.erl a forráskódot tartalmazó fájl: c(pelda). paranccsal - indítás: pelda:init(). ha az init a kezdofüggvény