A Mercury programozási nyelv

Adat-termek

Szintaktikájukat tekintve az adat-termek szokványos termek.

A Prologhoz viszonyítva találhatunk néhány különbséget. Az első különbség, hogy Mercury-ban a dupla idézőjelek közé tett sztingek atomiak, ezek nem rövidítései a karakterkódokból álló listáknak. A második, hogy a Mercury számos kiterjesztéssel bővíti a Prolog termjeinek szintaxisát: a Mercury termek tartalmazhatnak egy rekord mezőit kiválasztó és módisító kifejezéseket, feltételes (if-then-else) kifejezéseket, függvény applikációkat, magasabbrendű-függvények applikációját, lambda kifejezéseket, és explicit típusminősítéseket.

Egy adat-term vagy egy változó, egy adat-funktor, vagy egy speciális adat-term. Egy speciális adat-term vagy egy feltételes kifejezés, egy rekord szintaxisú kifejezés, egy lambda kifejezés, egy magasabbrendű-függvények applikációja, vagy egy explicit típusminősítés.

Adat-funktorok

Egy adat-funktor egy egész-, egy lebegőpontos-, egy sztring- vagy egy karakter-literál (bármilyen egyetlen karakterből álló név), egy név, vagy egy összetett (compound) adat-term. Egy összetett adat-term olyan összetett term, melynek formája nem egyezik meg a speciális adattermekével (lásd Adat-termek), és amelyeknek argumentumai szintén adat-termek. Ha az adat-funktor egy név vagy egy összetett adat-term, akkor a legfelső szintű funktora által megnevezett függvénynek, predikátumnak vagy adat-konstruktornak deklaráltnak kell lennie a programban, vagy egy importált modul interfészében.

Rekord szintaxis

A rekord szintaxis kényelmes módot biztosít arra, hogy adat-konstruktorok mezőit kiválasszuk vagy módosítsuk, függetlenül a konstruktor definíciójától. Egy rekord szintaxis kifejezés mező kiválasztó vagy módosító függvények hívásainak sorozatává transzformálódik (lásd Field access functions).

Egy mezőhatározó egy név vagy egy összetett adat-term. Egymástól a ^ karakterrel elválsztott mezőhatározók listája egy mezőlista. A field, field1 ^ field2 és field1(A) ^ field2(B, C) kifejezések mind érvényes mezőlisták.

Ha egy mezőhatározó legfelsőbb szintű funktora a field/N, akkor kell lennie egy látható field/(N + 1) kiválasztó függvénynek. Ha a mezőhatározó egy mező módosító kifejezésben fordul elő, akkor kell lennie egy 'field :='/(N + 2) nevű, látható módosító függvénynek is.

A rekord szintaxis kifejezések a következő formák egyikével rendelkeznek. Létezik rekord szintaxis DCG célok esetén is (lásd DCG-goals), ami hasonló funkcionalitást biztosít az előzőekhez azzal a kivétellel, hogy a DCG klóz DCG argumentumjaira hatnak.

Term ^ field_list
Mező kiválasztás. Mindegzik mezőhatározó esetén a field_list-ből rendre végrehajtja a neki megfelelő kiválasztó függvényt.

Term-nek érvényes adat-termnek kell lennie. field_list-nek érvényes mezőlistának kell lennie.

A mező kiválasztást a következő szabályok felhasználásával alakítjuk át:

	    transform(Term ^ Field(Arg1, ...)) = Field(Arg1, ..., Term).
transform(Term ^ Field(Arg1, ...) ^ Rest) = transform(Field(Arg1, ..., Term) ^ Rest).

Példák:

Term ^ field ekvivalens a field(Term) kifejezéssel.

Term ^ field(Arg) ekvivalens a field(Arg, Term) kifejezéssel.

Term ^ field1(Arg1) ^ field2(Arg2, Arg3) ekvivalens a field2(Arg2, Arg3, field1(Arg1, Term)) kifejezéssel.

Term ^ field_list := FieldValue
Mező módosítás, visszaadja a Term egy másolatát úgy, hogy a hogy a field_list által meghatározott mező értékét lecseréli a FieldValue értékre.

Term-nek érvényes adat-termnek kell lennie. field_list-nek érvényes mezőlistának kell lennie.

A mező módosítás átalakítása a következő szabályok szerint történik:

	    transform(Term ^ Field(Arg1, ...) := FieldValue) = 'Field :='(Arg1, ..., Term, FieldValue)).
transform(Term0 ^ Field(Arg1, ...) ^ Rest := FieldValue) = Term :- OldFieldValue = Field(Arg1, ..., Term0),
NewFieldValue = transform(OldFieldValue ^ Rest := FieldValue),
Term = 'Field :='(Arg1, ..., Term0, NewFieldValue).

Példák:

Term ^ field := FieldValue ekvivalens a következővel: 'field :='(Term, FieldValue).

Term ^ field(Arg) := FieldValue ekvivalens a következővel: 'field :='(Arg, Term, FieldValue).

Term ^ field1(Arg1) ^ field2(Arg2) := FieldValue ekvivalens a következő kóddal:

	    OldField1 = field1(Arg1, Term),
NewField1 = 'field2 :='(Arg2, OldField1, FieldValue),
Result = 'field1 :='(Arg1, Term, NewField1)

Egyesítő kifejezések

Egy egyesítő kifejezés egy, a következő formájú kifejezés:

    X @ Y

ahol X és Y adat-termek.

Az egyesítő kifejezés jelentése a következő: az argumentumok egyesítése után a kifejezés ekvivalens ezzel az egyesített értékkel.

A szigorúan szekvenciális operációs szemantikája (lásd Szemantikák) egy X @ Y kifejezésnek a következő: a kifejezést helyettesítjük egy Z friss változóval, és közvetlenül Z kiértékelése után a Z = X, Z = Y konjugációt értékeljük ki.

Például a

    p(X @ f(_, _), X).

ekvivalens a következővel:

    p(H1, H2) :- H1 = X,
H1 = f(_, _),
H2 = X.

Az egyesítő kifejezések hasznosak, ha ún. switch kifejezést írunk (lásd Determinism checking and inference). Ha switch kifejezésben szerepel, akkor az egyesítő kifejezés argumentumait megvizsgáljuk. Egy ezzel ekvivalens, a felhasználó által definiált függvény esetén nem ez történne.

Feltételes kifejezések

Egy feltételes kifejezés egy, a következő két formájú kifejezés:

(if Goal then Expression1 else Expression2)
(Goal -> Expression1 ; Expression2)

Goal egy érvényes cél; Expression1 és Expression2 adat-termek. A feltételes kifejezés szemantikája a következő: ha Goal igaz, akkor a kifejezés jelentése Expression1, egyébként Expression2.

Ha Goal egy some [X, Y, Z] ... alakú cél, akkor az X, Y és Z hatáskörébe beletartozik Expression1 is.

Lambda kifejezések

Egy lambda kifejezés egy összetett term, melynek alakja egyike a következőknek:

lambda([Arg1::Mode1, Arg2::Mode2, ...] is Det, Goal)
pred(Arg1::Mode1, Arg2::Mode2, ...) is Det :- Goal)
pred(Arg1::Mode1, Arg2::Mode2, ..., DCGMode0, DCGMode1) is Det --> DCGGoal
func(Arg1::Mode1, Arg2::Mode2, ...) = (Result::Mode) is Det :- Goal
func(Arg1, Arg2, ...) = (Result) is Det :- Goal
func(Arg1, Arg2, ...) = Result :- Goal

ahol Arg1, Arg2, ... nulla vagy több adat-term, Result egy adat-term, Mode1, Mode2, ... nulla vagy több módjelző (lásd Módok), DCGMode0 és DCGMode1 módjelzők (lásd Módok), Det egy determinizmusjelző (lásd Determinizmus), Goal egy cél (lásd Célok), valamint DCGGoal egy DCG-cél (lásd DCG-Célok). A :- Goal rész opcionális; ha nincs megadva, akkor feltételezzük helyette a :- true részt. Egy lambda kifejezés az a magasabb rendű predikátum vagy függvény termet jelöli, melynek értéke az a predikátum vagy függvény melyet a megadott cél és az argumentumok határoznak meg. Lásd Magasabb rendű programozás.

Egy lambda kifejezés új hatókört vezet be: minden változó, amely az Arg1, Arg2, ... argumentumokban fordul elő, lokálisan kvantált, vagyis a lambda kifejezésben előforduló változók különböző változókat jelölnek minden olyan, azonos nevű változótól, amik a lambda kifejezésen kívül fordulnak elő. Azokra a változókra, amik a Result-ban vagy a Goal-ban, de az argumentumokban nem fordulnak elő, a Mercury implicit kvantálásra vonatkozó szokásos szabályai vonatkoznak (lásd Implicit kvantálás).

A lambda kifejezések azon formája, melyben a lambda a legmagasabb szintű funktor, elavúltnak tekintett; kérjük használják a pred formájút helyette.

A lambda kifejezések azon formája, melyben a --> a legmagasabb szintű funktor, egy szintaktikai rövidítés: ugyanis a következő formájú kifejezés:

pred(Var1::Mode1, Var2::Mode2, ..., DCGMode0, DCGMode1) is Det --> DCGGoal

ekvivalens a következő kifejezéssel:

pred(Var1::Mode1, Var2::Mode2, ..., DCGVar0::DCGMode0, DCGVar1::DCGMode1) is Det :- Goal

ahol DCGVar0 és DCGVar1 friss változók, és Goal az eredménye a DCG-transform(DCGVar0, DCGVar1, DCGGoal) predikátumnak, ahol a DCG-transform a DCG-célok részben meghatározott függvény.

Magasabb rendű függvény applikációk

Egy magasabb rendű függvény applikáció egy olyan összetett term, melynek a formája a következők egyike:

    apply(Func, Arg1, Arg2, ..., ArgN)
FuncVar(Arg1, Arg2, ..., ArgN)

ahol N >= 0, Func egy term, melynek típusa func(T1, T2, ..., Tn) = T, FuncVar egy ugyanilyen típusú változó, valamint Arg1, Arg2, ..., ArgN rendre T1, T2, ..., Tn típusú termek. A magasabb rendű függvény applikáció term típusa T. A kifejezés az az eredményt jelöli, amit akkor kapunk, ha a megadott függvényt a megadott argumentumokra alkalmazzuk. Bövebben lásd a Magasabb rendű programozás részt.

Explicit típus minősítések

Az explicit típus minősítések alkalmanként hasznosak lehetnek abban, hogy a túlterhelések vagy a polimorf típusok miatt felmerülő kétértelmű kifejezéseket feloldjuk.

Egy explicit típus minősítés kifejezés egy olyan term, melynek a formája a következő:

    with_type(Term, Type)

vagy az ezzel ekvivalens, gyakrabban használt formában:

    Term `with_type` Type
  

Term-nek érvényes adat-termnek kell lennie. Type-nak érvényes típusnak kell lennie (lásd Típusok).

Egy explicit típus minősítés kifejezés kényszeríti a megadott termet, hogy a megadott típusa legyen. Ettől eltekintve, egy explicit típus kényszerítés kifejezés értelme pontosan megegyezik a megadott Term-ével.