Minden eljáráshoz adjunk meg egy fejkommentet, amely leirja milyen logikai összefüggést valósit meg az eljárás. Próbáljunk a paraméterek bemenő/kimenő jellegétől elvonatkoztatni, azaz csak az eljárás által megvalósitandó reláció jellemzőit leírni.
A fejkomment alakja:
<eljárásfej>: <egy vagy több kijelentő mondat, amelyben az összes argumentum szerepel>
Ha vannak megszorítások a paraméterek bemenő/kimenő jellegére,
azt külön mondatban írjuk le, vagy az SWI kézikőnyvben/help-rendszerben
használt jelőléssel a paraméter elé írt jelekkel adjuk meg (+
= bemenő, -
= kimenő, ?
= be- és kimenő)
Például:
Ha az eljárás egy olyan klózzal kezdődik, amelyben minden fej-argumentumot egy (megnevezett) változó jelöl, akkor a fenti alakban nem szükséges az <eljárásfej> megadása, és a kezdő klózfej argumentumneveire hivatkozhatunk a fejkommentben. Példa:
Az egy eljáráshoz tartozó klózokat között ne hagyjunk üres sort. Ha az egyes klózokhoz kommentárt kívánunk fűzni, akkor ezt a klózfej vagy a hívás után a jobb szélen tegyük. Eljárások közé mindig tegyünk legalább egy üres sort.
Az egy eljáráshoz tartozó klózok mindig folyamatosan egymás után következzenek, közéjük ne szúrjunk be idegen eljárásokat.
Ebben a részben néhány típushibára hívjuk fel a figyelmet.
=/2
, pl. Lista = [Fej|Farok]
, általános egyesités
(lásd még az alábbi tanácsokat az
=/2
-ről).
==/2
, két kifejezés azonossága, nagyon ritkán van rá szükség.
is/2
, pl. X is A+B
, a jobboldali aritmetikai
kifejezést kiértékeli és egyesíti a baloldallal. A baloldalon csak szám,
vagy változó értelmes, kifejezés nem!
=:=/2
, pl. X mod 7 =:= 0
, mindkét oldalon
aritmetikai kifejezést vár, kiértékeli ezeket és értékük egyenlőségét
vizsgálja.
=/2
-ről
mondottakat is):
append/3
: az append
használata szinte
mindig elkerülhető akkumulátorváltozók használatával. A programok írásánál
vegyük figyelembe, hogy az append
az első argumentum-lista
hosszával arányos számú lépésben fut le.
p/2
második klóza helyettesíti az r
eljárást (pontosabban a hívás helyén r(X)
helyett p(X, 0)
szerepel). Ez a séma feltétlenül kerülendő, hiszen mind a program
hatékonyságát mind az olvashatóságát rontja.
Mindig olyan változóneveket használjunk amelyek a változó jelentésével
asszociálhatóak. Lehetőleg kerüljük az A, B, C, X, Y, Z,
stb. változóneveket. Egy hasznos konvenció a következő: ha egy listaelem
jelölésére a V változónevet használjuk, akkor az ebből képzett lista
jelölésére használjuk a VL
vagy
VLista
(angol nyelven írt programban a
Vs
) jelölést.
Az egy klózban egyszer előforduló változókat mindig aláhúzással, vagy aláhúzással kezdődő változónévvel jelöljük. Aláhúzással kezdődő változónevet ne használjunk többször egy klózban.
Használjuk ki a Prolog egyszerűsitő
jelöléseit, pl. [A|[B|C]]
helyett mindig írjuk a
[A,B|C]
kifejezést!
A diszjunkciók túlzott használata áttekinthetetlenné teszi a programot. Ezért lehetőleg ne használjunk diszjunkciót! Gondoljuk meg, nem vezet-e be a diszjunkció felesleges többszörös megoldásokat.
Az =/2
beépített eljárás használata általában
kerülendő. Az =
eljárás hívásai többnyire kiküszöbölhetők úgy,
hogy az egyik oldalon szereplő változó minden előfordulását a másik oldalra
cseréljük.
Például:
=/2
eljárás használatára szükség lehet diszjunkciókban,
illetve vágót tartalmazó klózokban .
Sokszor nagy a csábítás arra, hogy egy speciális esetre, amikor az eljárás esetleg egyszerübben is végrehajtható, egy külön klózt írjunk. Ez azonban a programot kevésbé áttekinthetővé teszi és ugyanannak a megoldásnak többszöri előállítását is eredményezheti. Ez az utóbbi jelenség rendkívül veszélyes, mert nagy lassulásokat okozhat, kereső jellegű programoknál.
Ezért azt javasoljuk, hogy kerüljük a speciális esetek külön kezelését! Példa:
append
eljárás a megoldások többségét kétszer fogja
kiadni. Egy vágó beszúrásával ezen segíthetünk, de akkor megszűnik az
append visszafelé való használhatósága. Egy másik javítási lehetőség az,
hogy az append utolsó klózában egyszerre két elemet emelünk át az első és
harmadik argumentum között, amivel persze a második klóz megszűnik
felesleges lenni.
Egy az előzővel rokon problémaforrás: vigyázzunk, hogy minden megoldást csak egyszer állítsunk elő. Tipikus hiba, hogy a rekurzió leállító feltételét egy külön klózban is, és a rekurzív klózba tett diszjunkcióban is vizsgáljuk. Ez egy algoritmikus, vagy funkcionális nyelvnél nem hiba, csak felesleges és hatékonyságcsökkenést jelent. Prologban viszont az adott eljárás többszörösen fog sikerülni, ami többszörös megoldások megjelenését és hatványozott lassulást okozhat. Példa:
Először mindenképpen próbáljunk meg megoldást találni vágó használata nélkül. Ezután, ha hatékonysági okokból fontosnak tartjuk a vágó bevezetését, akkor nagyon alaposan gondoljuk meg, hogy hová helyezzük a vágót a klózban. Nagyon gyakran szükség lehet a fejbeli egyesítéseknek explicit egyenlőségekké való alakítására, hogy ezek a vágó utánra kerüljenek. Például tekintsünk először egy vágó nélküli megoldást egy egyszerű problémára.
?-duplazott([1], [1]).
hívás
sikeresen lefut. A helyes megoldás:
Megjegyzéseket a szeredi@iqsoft.hu címre várunk.
Utoljára Szeredi Péter módosította 1995. december 5-én.