• Nem Talált Eredményt

Mercury

In document Prolog programozási nyelv (Pldal 70-73)

hogy milyen modulokat szeretnénk felhasználni, esetünkben ez a standard input/output, ami itt io névre hallgat.

Minden Mercury programban szükséges egy main predikátum; mivel most csak ez az egy modul alkotja az egész programot, így ebben a modulban is szerepelnie kell. Miután a program a környezetével kapcsolatot tart, így szükséges az input és az output paraméter. A Mercury-nál meg kell adni, hogy milyen módon használjuk az argumentumokat. Esetünkben az input paraméter destruktív, azaz felhasználás után lényegében törlődik (a környezet megváltozik a program hatására), az output paraméter unique, azaz egyértelmű, a program végrehajtása pedig determinisztikus. Már majdnem mindent elmondtunk egyetlen predikátumunkról, csak a kód hiányzik. Galád módon ezt DCG szintaxisban írtuk meg. Valójában a main két paramétere az io__write_string két paramétere lesz. A programot a mmc --make hello utasítással fordíthatjuk le.

1.1. DOG+ANT=CAT

A feladatgyűjteményben szerepel betűrejtvény programja Prolog nyelven implementálva. Lássuk itt ez hogyan programozható Mercury nyelven! A program fejlécében egy cc_multi kulcsszó szerepel, ez jelzi, hogy esetleg több megoldása is van a rejtvénynek, mi csak az elsőt ismerhetjük meg. Ez erősen összefügg azzal, hogy a kiírásnál a backtrack nem működik! Mivel számolgatunk, listát használunk, megnő a betöltendő modulok száma is.

:- import_module int, list, string.

A main már nem tartalmaz túl sok ismeretlen dolgot. Ami érdekesség, hogy használhatjuk az if-then-else

pick(Ds0,G,Ds1),

Az előző predikátum használt egy segédpredikátumot, amit már jól ismerünk, igaz más néven:

:- pred pick(list(int)::in, int::out, char*-nak felel meg. A lista csakis azonos típusú elemek sorozata, benne számot karakterrel nem keverhetünk;

nem úgy, mint azt több Prolog példaprogramban megtettem. A lista definíciójához hasonlóan megadható a fa adattípus is. Ez még általános (polimorf) típus, ebből készíthető egész-fa, betű-fa, stb. Szerencsére készíthetőek pofimorf predikátumok, mint például a lista hossza, melyben nem érdekes, hogy a listaelemek milyen típusúak.

Definiálhatóak absztrakt típusok, így egy modul használójának nem fontos tudnia, hogy a modul milyen adatszerkezetet használ.

:- type list(T) ---> [] ; [T|list(T)].

:- type tree(T) ---> leaf ; branch(tree(T), T, tree(T)).

A tuple lehetővé teszi több különféle típus keverését: {111,'b'}.

Lehetőség van új, összetett típusok definiálására:

:- type playing card ---> card(rank, suit) ; joker.

:- type rank ---> ace ; two ; three ; four ; five ; six ; seven ; eight

; nine ; ten ; jack ; queen ; king.

:- type suit ---> clubs ; diamonds ; hearts ; spades.

A nyelvben definiálhatunk rekordokat, amelyet az alábbi módon használhatunk fel.

:- type bank account --->

account( name :: string, account_no :: int, funds :: float ).

( if BankAcct^funds >= RequestedSum then ... debit RequestedSum from BankAcct ...

else

... reject debit request ...

)

1.3. Magasabb rendű típusok

A funkcionális nyelvekben elengedhetetlen azon függvények használata, ahol a függvény egyik paramétere egy függvény. Az egyik legismertebb ilyen függvény a map, melynél az egyik paraméter egy l lista, míg a másik egy f függvény, és eredményül egy olyan listát kapunk, ahol az l lista minden egyes elemére alkalmaztuk az f függvényt. Kis bűvészkedéssel ez megvalósítható Prologban is, csak az =.. operátort kell használni predikátumok felbontására és összeállítására. Lássuk hogyan megy ez a Mercury-ban! A map függvény második argumentuma egy T1 típusú lista, míg az első egy T1 input/T2 output típusú függvény. A map kimenete így T2 típusú lista lesz.

:- func map(func(T1)=T2,list(T1)) =list(T2).

map(_,[]) = [].

map(F,[X|Xs]) = [F(X)|map(F,Xs)].

A másik speciális függvény a filter. Ennek szintén egy l listát és egy f logikai értékű függvényt kell átadni. A függvény pedig egy listát ad vissza, melyben l azon x elemei találhatóak, melyekre f(x) igaz. Az előbbivel hasonló bűvészkedéssel ez Prolog-ban is megvalósítható. A Mercury esetén egy kicsit általánosabb filter predikátumot implementálunk, itt a bemenő listát két részre bontjuk, azokra az elemekre, melyre a P predikátum teljesül, illetve azokra, melyekre nem.

:- pred filter(pred(T), list(T), list(T), list(T) ).

:- mode filter(in(pred(in) is semidet), in, out, out ) is det.

filter(_,[],[],[]). kivédésére láttuk a vágás használatát; felhasználható a predikátumok indexelése, s mindenféle apróbb trükkök is bevethetőek, hogy a program futását gyorsítsuk. A Prolog számára egy predikátumot írtunk le, melyet gyakran több irányban is használhattunk. A Mercury már fordításkor eldönti a használat irányát, ezzel jelentősen gyorsíthatja a program futását. Viszont ehhez meg kell adnunk, hogy hogy milyen irányokban hogyan működik a predikátumunk: használhattuk, minden specifikáció nélkül. Erre itt most nincs lehetőség, minden (használni kívánt) lehetőséget pontosan meg kell adni.

:- pred append(list(T), list(T), list(T)).

:- mode append(in, in, out) is det.

:- mode append(in, out, in) is semidet.

:- mode append(out, in, in) is semidet.

:- mode append(out, out, in) is multi.

append(Xs, Ys, Zs) :- ( Xs = [], Zs = Ys ;

Xs = [Hd | Tl], append(Tl, Ys, Zs0), Zs = [Hd | Zs0]).

Lássuk, mit is jelent a fejlécben szereplő mode utasítássorozat. Ha az összefűzendő két lista ismert, akkor egyértelmű az eredmény. Ha a teljes lista és a prefixe/suffixe ismert, akkor ezek vagy illeszkednek, s egyértelmű

az eredmény; vagy nem, s akkor nincs output. Ha pedig csak a teljes lista ismert, akkor azt rendszerint több módon is szét lehet bontani prefixre és suffixre.

Az előbbiek ismeretében remélem érthető a következő program, amelyben láthatjuk, hogy a predikátumok

:- mode factorial(in, out) is det.

:- implementation.

:- import_module int.

factorial(N, F) :- ( if N =< 0 then F = 1

else factorial(N - 1, F0),F = N * F0).

Egy ilyen predikátum megfogalmazható függvényként is, ám a függvény típusait is be kell állítanunk.

:- func fibonacci(int) = int.

:- mode fibonacci(in) = out is det.

fibonacci(N) = F :- ( if N =< 2 then F = 1

else F = fibonacci(N - 1) + fibonacci(N - 2)).

A nyelv folyamatosan fejlődik, a honlapján meg lehet tekinteni az aktuális fejlesztéseket.

In document Prolog programozási nyelv (Pldal 70-73)