SML Basis Library

17.1. Kérdés.
Azt szeretném megkérdezni, hogy mi az az option, ill. a unit típus? és ehhez kapcsolódva, hogy mit is csinál pontosan az isSome, getOpt, valOf, getItem és mapPartial? Nem igazán tudtam rájönni ezekre a jegyzetből. Egyáltalán kellenek ezek a dolgok?

17.1. Válasz.
Oktató: Kellenek. Az előadásokon többször elmagyaráztam a jelentésüket. Az előadásdiákon, az SML Basis Library-ben az Option és a General modulokban, továbbá a GYIK jelen fejezetében ezekről a dolgokról elég részletes magyarázatok olvashatók.

17.2. Kérdés.
Az sml jegyzetben a Structure Option [az Option modul] leírásában van ez a SOME, de fogalmam sincs, hogy mit jelent. Ha valaki meg tudná mondani, igen sokat segítene (csak a motiváció kedvéért).

17.2. Válasz.
Hallgató: Van úgy, hogy azt szeretnénk, hogy egy azonosító értékül felvehesse azt is, hogy semmi. Pl. írunk egy 'lista első eleme' függvényt, és azt szeretnénk, hogy a függvényünk az üres listára azt mondhassa, hogy nincs eredmény. Kb. erre való az 'a option típus.

Amikor az 'a option típust használva azt akarjuk értékül adni, hogy semmi, akkor a NONE adatkonstruktorállandót kell használnunk. Ha pedig valódi értéket akarunk értékül adni, akkor a SOME adatkonstruktorfüggvényt.

Az 'a option deklarációja ez:

datatype 'a option = SOME of 'a | NONE;
Tehát vagy hordoz valamilyen értéket, ekkor SOME ertek alakú; vagy nem, ekkor NONE alakú. Példa:

fun listafeje (x::xs) = SOME x
   |listafeje [] = NONE;
Kis kényelmetlenség, hogy minden esetben mintaillesztést (vagy ezt elvégző függvényhívást) kell használnunk, hogy a hordozott értékhez hozzáférjünk, már ha egyáltalán van hordozott érték.

Szerencsére vannak könyvtári függvények (pl. List.mapPartial), amelyek ,,eltakarják'' ezt a komplexitást.

Remélem, megvilágítottam a dolgot (és nem tévedtem).

17.3. Monológ.
Oktató: Az SML könyvtárak használatáról

A könyvtári függvényeket általában a Konyvtar.fuggveny teljes - vagy másképpen minősített, angolul qualified - névvel lehet elérni, pl. Int.fromString. Fontos, hogy Unix/Linux alatt a kis- és nagybetűket a könyvtár- és függvénynevekben meg kell különböztetni, azaz Int és nem int vagy INT. A programok hordozhatósága érdekében az írásmódra Windows alatt is ügyelni kell. A pontos írásmódot a könyvtári függvényeket ismertető leírások tartalmazzák.

Ha a programjukat - pl. az mosmlc fordítóval - lefordítják le és összeszerkesztik (ezt teszi a kis- és nagyházik beadásakor a tesztkörnyezet is), akkor a könyvtárak használata általában nem jelent további technikai nehézséget.

Az mosml értelmező használatakor viszont a program betöltése előtt a felhasználandó könyvtárakat be kell tölteni, ezt az

app load ["Konyvtar1", "Konyvtar2", ...];
vagy egyetlen könyvtár betöltése esetén a

load "Konyvtar";
szerkezetű függvényalkalmazással tehetik meg. Példák:

app load ["Int", "Binaryset"];

load "Regex";
Fontos, hogy ezt a függvényhívást, ha a programot le fogják fordítani, ne írják bele a programjukba, mert az mosmlc fordító ,,elhasal'' rajta.

Bizonyos gyakran használt könyvtárakat (pl. String, List) nem kell betölteni, mert induláskor az mosml értelmező ezeket automatikusan betölti.

Ha nem akarják kiírni egy-egy könyvtári függvény teljes nevét (ami egyébként hasznos, többek között javítja a program olvashatóságát), akkor az adott könyvtárat megnyithatják az open Konyvtar deklarációval, pl.

open Int;
Ettől kezdve a min hívás azonos lesz az Int.min hívással. Ezt a megoldást, mint írtuk, mégsem javasoljuk, mert nehezebben olvashatóvá teszi a programot.

17.4. Kérdés.
Nem tudja valaki, hogy hogyan lehet egy SML könyvtárat betölteni (pl. Real), mert az ETS nem ismeri a mosml-ben használt load-ot?

17.4. Válasz.
Oktató: Nem kell betölteni, elég a minősített nevet megadni (pl. Math.sin). A gyakran használt, azaz az Int, Real, Char, String, List stb. könyvtárak esetében a függvények döntő többsége elé a könyvtár nevét ki sem kell írni, mert ezeket belső függvényként kezeli az mosml.

A load csak az ún. interaktív módban, azaz mosml-ben használható (akárcsak a use). Az ETS az mosmlc fordítóval lefordítja a programot a futtatása előtt, és a szükséges modulokat automatikusan betölti.

17.5. Kérdés.
Mi az oka annak, hogy bizonyos könyvtári listakezelő függvények, amelyek pl. a list.sig-ben le vannak írva, nem működnek, ha betöltöm a könyvtárat. Pl. revAppend, mapPartial, last, nth.

17.5. Válasz.
Oktató: Alighanem az az oka, hogy a könyvtárnevet ki kell írni, mégpedig nagy kezdőbetűvel: List.nth; List.revAppend, mind Unix/Linux, mind Windows alatt. Más okát nem látom.

Megoldás lehet az is, hogy láthatóvá teszi a kérdéses könyvtár, pl. a List könyvtár tartalmát, így: open List.

17.6. Kérdés.
Egy roppant egyszerű kérdésem van: hogy hívják azt a beépített függvényt, amely egy int argumentumra a hozzá tartozó char típusú értéket adja eredményül?

17.6. Válasz.
Oktató: A függvény rövid neve chr, teljes neve Char.chr. Példa:

- chr(ord #"a" );
> val it = #"a" : char

17.7. Kérdés.
Kérdésem az sml gyakorlórendszer egyik feladatához kapcsolódik: be kellene töltenem a Real könyvtárat (load "Real"), amit a gyakorlórendszer nekem nem szeret. Biztosan van valami más megoldás, amihez nem kell a Real.fromInt, de nem jövök rá.

17.7. Válasz.
Oktató: A konverziót a real, teljes nevén a General.real függvénnyel is elvégezheti. De használhatja a Real.fromInt függényt is. A Real könyvtárat ehhez nem kell betöltenie, mert az mosmlc maga betölti, ha szüksége van rá. A load ugyanis, amint azt ebben a fejezetben másutt már leírtam, csak az interaktív mosml-környezetben használható.

17.8. Kérdés.
Az lenne a nagy problémám, hogy írtam egy gagyi kis sml progit, de sajnos nem akar működni, és fogalmam sincs, hogy miért nem. Hibának kiírja hogy ,,kezeletlen kivétel: subscript'' !!!???.

De vajon miért? Szerintem, amibe bele tud kötni, az ez a sor:

if String.sub(xs, String.size xs) = ...
Valószínűleg a sub-bal kötekszik, de miért? (Egyébként csak annyit még, hogy ez egy gyakorlórendszerbeli feladat, mégpedig a komplista nevű).

17.8. Válasz.
Oktató: Természetesen azért kötekszik, mert érvénytelen indexet kapott. Ugyanis 0-tól kezdve indexel a String.sub, amint a következő részlet is mutatja:

- String.sub ("abc", 1);
> val it = #"b" : char

17.9. Kérdés.
Most két függvényt nem értek és nem találok sehol: a String.tokens-t és az as-t. Mit csinálnak ezek? Hogyan kell őket használni?

17.9. Válasz.
Oktató: A String.tokens és a hozzá hasonló String.fields függvény leírása megtalálható a String könyvtárban; ha telepítette az mosml-t, a saját gépén a .../mosml/lib mappában találja meg, egyébként a weben html-változatban is megtalálhatja a <http://www.dina.kvl.dk/~sestoft/mosmllib/String.html> címen.

Az as nem függvény, hanem kulcsszó. Lásd például az (xxs as x::xs) ún. réteges mintában (angolul: layered pattern), ahol a teljes lista xxs néven, a feje x, a farka xs néven érhető el egy függvénydefinícióban annak a klóznak a törzsében, amelynek a fejében ez a minta szerepel.

17.10. Kérdés.
Valaki el tudná magyarázni, hogyan is működik a String.tokens függvény?

17.10. Válasz.
Hallgató: Valahogy így:

- String.tokens (fn #" " => true
                | _ => false) "sfew rehwqo rejio341";
> val it = ["sfew", "rehwqo", "rejio341"] : string list
Tehát az első argumentum egy predikátum (azaz bool típusú eredményt adó függvény), amely megmondja, hogy mit tekintünk elválasztó karakternek - szeparátornak - (true), és mit nem (false); a második argumentum meg a tokenizálandó füzér (string). A függvény eredménye egy, a tokeneket tartalmazó, string típusú elemekből álló lista. Az egymás mellett álló szeparátorokat a függvény egyetlen szeparátornak tekinti; a szeparátorokat ,,megeszi''.

Remélem, segítettem. Egyébként érdemes próbálgatni mosml-ben, ha nem érted.

17.11. Kérdés.
Nem tudja valaki, hogyan lehet két int-et binarisan AND-elni, illetve OR-olni?

17.11. Válasz.
Oktató: int típusú (előjeles egész) értéket nem lehet, word és word8 típusú (előjel nélküli egész) értéket lehet; lásd a Word.andb, Word.orb, Word8.andb és Word8.orb függvényeket. fromInt és toInt néven ugyanott konverziós függvények is vannak.


Deklaratív programozás - FP-GYIK
2005. március 1.