Újabb lépcsőfokok



    Az előző bejegyzés is egy kedvcsináló írás volt, ez is az lesz. Akkor egy nem teljesen elmagyarázott példát is bemutattam. Lássuk mi mit csinál?

object
XmlHello
extends
Application
{

  
val
xml = (

    
<!– An xml with
comment –>

    
<hello
who=
{java.util.Locale.getDefault().getDisplayCountry()}
from=
"scala"></hello>

    
<tag attribute="value">
      
<hello who="dear
reader"
from="author"/>

    
</tag>)

  for
(
nodes
<-
xml;
//Selecting the nodes of xml
(scala.xml.Elem).

        node
<-
nodes
\\ "hello";
//Finding the nodes with label ==
"hello".

        who
<-
node
attribute
"who"
//Selecting those which has "who"
attribute.

  )

    println(node.label
+ "
"
+
who)
//Printing the label and the who
attribute value.
}

    Azt, hogy ez egy futtatható program lesz,
gondolom nem kellene megemlítenem sem. Létrehozunk egy XML
dokumentumot, melyre mutató referenciát rögtön át is adjuk egy nem
változtatható referencia tárolónak, ez lenne az amit xmlként
azonosítottunk. A Java nyelvvel ellentétben itt nem lehet később
értéket kapnia. Természetesen itt is lehetnek változó referencia
tárolók, azokat a var kulcsszóval vezethetjük be. Az XML dokumentumot ()-ek közé zártuk (a típusa pedig scala.xml.NodeBuffer). Ez a fejlesztőkörnyezet hiányossága miatt volt szükséges, enélkül nem tudta volna lefordítani. Azonban egyébként is praktikus lehet kitenni a zárójelet, nehogy véletlenül csak az XML-es megjegyzés legyen az a dokumentum amit később használhatunk.
    Az első hello tag who attribútumában megfigyelhetjük, hogy egy Scala kifejezésből veszi fel az értékét. Ez éppenséggel lehetne Java kód is, így lehet az aktuális Locale országának szépen kinéző változatát megkapni. Természetesen itt sem kötelező kiírni a csomagnevet, lehet használni az import kulcsszót a későbbi gépelés megspórolásához, az olvashatóság javításához. (Azonban kissé bonyolultabb mint Java-ban, így erről igény esetén csak később. (Például lehetővé teszi, hogy átnevezéssel hivatkozzunk valamire kódunkban.))
    Azt hiszem az XML létrehozásáról ennyi elegendő volt. Nézzük a többit!
    Ott egy ismerős for
Azonban mintha túl sok minden lenne utána. Nos, Scala-ban nincs for ciklus. Az egyébként is helyettesíthető while ciklussal szükség esetén. Helyette a fort
sokkal érdekesebben lehet használni. Be lehet járni vele különféle
szekvenciákat, szűrni lehet azokból és akár az eredmény is lehet egy
újabb szekvencia. Elég hasznos, kényelmes lehet, ha jól használja az
ember.
    Először az XML dokumentum részein haladunk végig, ezekre később a nodes aktuális értékeivel hivatkozhatunk. A nodes egyes értékei a scala.xml.Comment, scala.xml.Elem
, scala.xml.Elem típusúak, (legspeciálisabb) közös ősük a scala.xml.Node absztrakt osztály. (Igen, a változónév és a megjegyzés is elég megtévesztő) A következő lépésben ezek közül kiválasztjuk azokat, melyek hello címkével rendelkeznek valahol (akár a belsejükben). Ezt a scala.xml.Node közvetlen ősében (scala.xml.NodeSeq – a név talán mégsem volt annyira megtévesztő) definiált \\(that: String): NodeSeq metódussal tehettük meg. Dehát nem is írtunk .-ot! Nos, igen. A Scala
támogatja a metódusok olyan hívási módját is (amennyiben nulla, vagy
egy paramétere van), amely olyan mintha operátorként használnánk. Így
lényegében végtelen sok operátort használhatunk. És igen, használhatunk
olyanmetódusneveket is, amelyeket Java esetén nem (de az adott futtatókörnyezet esetében igen). Így a \\ is használható. Amit ez csinál az hasonlít az XPath lekérdező nyelv hasonló műveletére: megkeresi az adott gyökérből kiindulva az összes illeszkedő scala.xml.Node-ot. Ezeknek a node azonosítót adtuk. A következő sorban ezek közül csak azokat választjuk ki, melyeknek van who attribútuma. Ehhez a
scala.xml.Node attribute(key: String): Option[Seq[Node]] metódusát használtuk (most is pontok nélkül). A hozzá tartozó scaladoc egy kissé idejétmúlt, mivel azt írja ha nincs hozzá key attribútum, akkor nullt ad vissza. Szerencsére nem így van, mivel akkor a példánk sem működne. Amit visszaad az egy scala.Option. Ennek pontosan két leszármazottja van, a scala.Some (egy osztály) és a scala.None (egy egyke objektum). Scala fordítóval nem is lehetne több. (Azonban Java-t, vagy más nyelvet is használva ez már nincs így…) Ezt úgy érték el, hogy a scala.Option osztályt ellátták a sealed kulcsszóval, emiatt csak vele egy fordítási egységben (állományban) lévő osztályok terjeszthetik ki, ezek pedig csak a felsoroltak.
    Ami meglepő, hogy a scala.Option esetén is alkalmazható a for (a scala.None-okat kihagyja, míg a scala.Some-okat megtartja), így az értékeket a who változóban elhelyezhetjük.
    A végén már csak ki kell írnunk a node címkéjét, illetve a who változó értékét egy szóközzel elválasztva és meg is kapjuk a korábban leírt eredményt.

    Sok mindenről lehetne még írni (akár programokról (ScalaCheck, lift, ), további nyelvi elemekről (eseti osztályok, egzisztenciális típus paraméterek, generikusok, ), vagy akár elméleti alapokról (monádok, katamorfizmus, kategória elmélet, ), technológiákról (IDE használat, különböző platformokra fejlesztés, )), azonban úgy tűnik senki sem szeretné egy olyan irányba terelgetni ezt a bemutatást ami tetszene neki. A végén kénytelen leszek magam dönteni. 🙂 (Esetleg hasznosabbak lennének Fortress-szel, vagy Nemerlével kapcsolatos bejegyzések?)
    Végül egy fejtörő: Mit csinál a következő programrészlet?

(""
/: (1 to
20)) ( (_,_).
_1
+ "_"
)
 
Nem egyszerű ugye? (Nos kissé csaltam is. Ennek nagy részéről még nem
írtam, de az egyik levelező listán előjött megoldásként és megtetszett.
A Perl kedvelők örömére idekerült. ;-))

Folytatás itt

This entry was posted in Scala. Bookmark the permalink.

Leave a comment