A Prolog programozási nyelv

Kivételkezelés

A tiszta Prologban egy predikátumhívás - feltéve, hogy keresési tere véges - meghiúsul vagy sikeresen lefut, esetlet választási pontot hagyva maga után. A beépített eljárások némelyike azonban bizonyos bemenő értékekre nem értelmezhető. Ilyen például az arg(I,T,A) hívás, ha T egyszerű term vagy I negatív, vagy a read(X) utasítás, ha formailag hibás termet kellene beolvasnia. Ilyenkor az aktuális eljáráshívás a megfelelő kivételt (exception) váltja ki és a hívás - sikeresség vagy meghiúsulás helyett - ezzel ér véget.

A kivételt mindig egy állandó vagy összetett term jelöli és mesterségesen is kiváltható a throw(Kivétel) utasítás segítségével, ahol Kivétel a kivételt jelölő term.

A kezeletlen kivételek mint futási hibák lépnek fel. Ezeket a Prolog fejlesztői környezet - a megfelelő hibaüzenet kiírásával - saját párbeszédciklusa szintjén kezeli.

A kivételkezelés eszköze a catch(Cél, KivételMinta, KezelőCél) utasítás.

A cath utasítások pontosan azon kivétekel kezelésére szolgálnak, amelyek az elsőargumantumban levő Cél kiértékelése során lépnek fel. A catch utasítások első argumentumát ezért védett (protected) argumentumnak nevezzük.

A catch utasítás tehár először meghívja az első, védett argumentumát paraméterező Cél célsorozatot. Amennyiben a Cél kiértékelése során nem lép fel kivétek, vagy ezt (ezeket) a Cél maga kezeli, akkor teljesen a Cél működése határozza meg a catch hívást. Ha azonban a Cél kiértékelése kereletlen kivételt vált ki (nevezzük ezt E-nek), akkor előszrö is készítünk E-ről egy friss másolatot (új változók bevezetésével), majd a Cél kiértékelése során végrehajtott összes változóillesztést töröljük, az itt létrehozott választási pontokkal, a hívási verembe betöltött hívási keretekkel, és általában minden visszaléptethető hatással együtt.

Ezután E friss másolatát és a KivételMinta termet illesztjük. Ha az illesztés sikeres, akkor a KezelőCél célsorozat határozza meg a catch utasítás további viselkedését. Ha azonban E friss másolata és a Kivételminta illesztése meghiúsul, akkor a környezet szempontjából úgy tekinthető, hogy a catch hívás váltotta ki az E kivételt. Ilyenkor azt mondjuk, hogy a catch utasítás tovább propagálja a kivételt.

Végül, ha E friss másolatának a Kivételmintával való illesztése ugyan sikeres, de a KezelőCél maga is kivált egy kezeletlen H kivételt, akkor a környezet szempontjából úgy tekinthető, hogy a catch utasítás váltotta ki a H kivételt. Ilyenkor is tovább propagálja tehár a kivételt.

A beépített eljárások mindig error(IsoErr, ImpErr) alakú kivételeket váltanak ki, ahol IsoErr a szabvány hibatermje, míg ImpErr rendszerfüggő:

| ?- catch( X is a, error(IsoErr,ImpErr), true). ImpErr = domain_error(_A is a,2,expression,a), IsoErr = type_error(evaluable,a/0)

Példa

Az olvas(Term) cél beolvas egy tetszőleges termet a szabványos bemenetről (ez alapesetben a billentyúzet), és az aktuális bejövő sor maradékát eldobja. Ha a bejövő term szintaktikusan hibás, kiírja az ISO szabványnak megfelelő hibatermet, majd újra olvas.

olvas(Term) :- catch( ( read(user,Term), skip_line(user) ), error(Hiba,_), ( ír(Hiba), olvas(Term) ) ). ír(Term) :- writeq(user,Term), nl(user). | ?- olvas(Term). |: a*(b+ . syntax_error('. cannot start an expression') |: a*(b+c. syntax_error(') or operator expected') |: a*(b+c). Term = a*(b+c)
throw/1, raise_exception/1
Hívási minta:
throw (@HibaKif)
raise_exception (@HibaKif)
Jelentés:
Se nem igaz, se nem hamis
Hatás:
Kiváltja a HibaKif hibahelyzetet
Kompatibilitás:
A két eljárás szinonima, de raise_exception/1
SICStus Prolog specifikus.
catch/3, on_exception/3
Hívási minta:
catch ( :+Cél, ?Minta, :+Hibaág )
on_exception ( ?Minta, :+Cél, :+Hibaág )
Argumentumok:
Cél - Az argumentum egy meghívható kifejezés
Minta - Az argumentum egy tetszőleges kifejezés
Hibaág - Az argumentum egy meghívható kifejezés
Jelentés:
Igaz, ha call(Cél) igaz, vagy ha a hívását megszakította throw/1 (vagy raise_exception/1) hívása egy olyan argumentummal, ami egyesíthető Minta-val és call(Hibaág) igaz.
Hatás:
Ha Cél végrehajtása során hibahelyzet nem fordul elő, futása azonos Cél-lal. Ha Cél-ban hiba van, a hibát leíró kifejezést egyesíti Minta-val. Ha ez sikeres, meghívja a Hibaág-at. Ellenkező esetben tovább göngyölíti a Prolog eljárásvermét további körülvevő catch/1 (on_exception/1) hívásokat keresve, és ezekre megismétli az eljárást.