Back to site
Since 2004, our University project has become the Internet's most widespread web hosting directory. Here we like to talk a lot about web servers, web development, networking and security services. It is, after all, our expertise. To make things better we've launched this science section with the free access to educational resources and important scientific material translated to different languages.

Prolog Dictionary

Aceasta versiune a dictionarului Prolog isi asuma sintaxa Prolog SWI. Cateva exemple si asuma un interpretor de comenzi Unix, la fel ca in Linux si MacOS X / Terminal.

Ar trebui sa folositi Dictionar Prolog sa se clarifice sau sa revizuiasca conceptele care le-ati cunoscut deja. Dictionar Prolog nu este o modalitate potrivita de a incepe sa invatati despre Prolog. Acestea fiind spuse, acest dictionar este conceput pentru a fi utilizat de catre programatori Prolog incepator si intermediar. Mai multe informatii despre Prolog pot fi gasite in documentatia SWI Prolog legate de mai sus.

Alte dictionare legate de:
Dictionar AI - URL: http://www.cse.unsw.edu.au/~billw/aidict.html
Dictionar Masina de invatare - URL: http://www.cse.unsw.edu.au/~billw/mldict.html
Dictionar NLP (procesarea limbajului natural) - URL: http://www.cse.unsw.edu.au/~billw/nlpdict.html

Alte locuri pentru a afla mai multe despre inteligenta artificiala includ AAAI (Asociatia Americana pentru Inteligenta Artificiala) AI Prezentare pagina sau de referinta Perioada de valabilitate AI

URL-ul acestui Dictionar Prolog este

Subiectele acoperite

Acest dictionar a fost limitat la conceptele acoperite in Prolog COMP9414 Inteligenta Artificiala de la Universitatea din New South Wales, Sydney. Acesta a fost ulterior extins pentru a acoperi conceptele Prolog in COMP9814 inteligenta artificiala, precum si extinderea. Oricum, aceasta nu acopera in prezent, anumite concepte care stau la baza Prolog (rezolutie, etc) De asemenea, nu acopera toate de ISO Prolog - Odata ce ati inteles totul in Dictionarul Prolog, ar trebui sa fie cu siguranta, gata sa se??scufunde in documentatia care vine cu tale favorite Prolog interpret.

Mai multe detalii despre Prolog pot fi gasite in notele de curs COMP9414 si COMP9814 notele de curs. Conceptele de baza Prolog - ca este, cele care fac obiectul / utilizate in COMP9414 - sunt marcate cu puncte verzi (•) in indicele de mai jos, si au, de asemenea, cuvant-titlu din articol despre ele in verde.

Index

A
B backtracking | bagof | obligatoriu | organism | Bratko | built-in functii | built-in predicate
C call | ceiling | clauza | comentarii | operatorii de comparatie | compound | consult | fluxul de intrare curent | fluxul de curent de iesire | cos | taiate,!
D debugging | declarative | tacerea: nu-ingrijire variabil | dinamica
E eficienta | mesaje de eroare si de avertizare | exp
F fail | fisiere | findall | float - functia | float - predicat | floor | functor
G Scopul
H halt | cap
Eu if-then-else | indentarea | infix operatorii | infix construit-in-uri | de intrare in Prolog | schema de intrare | integer | is
L Lista | listing | log
M member | memoisation | mod | More? | reciproca recursivitate
N gat | negatie, not, \+ | nl | nonvar | Numar | number
O once | op, infix, prefix, postfix, prioritate in Prolog | sau, disjunctia, ; | iesire in Prolog
P postfix | prioritate in Prolog | Predicatul | prin | print | Procedura de
Q interogare
R lectura | recursivitate | raport | Relatii si functii | repeat | retract, retractall | round | regula
S see | seeing | seen | setof | efecte secundare | sign | sin | Singleton variabilele | spy | sqrt | static | Structura | reusi
T tab | tan | tell | telling | termen lung | testare de tip, pe termen | testarea codul | told | urmarirea executarii, trace | true | truncate
U sublinia | unificare, =, \= | univ
V var | variabila
W spatiu alb | write | scris
= | \= | =.. | ! | ; | + -? argumente | -> | :- | \+ | == | \== | =:= | =\= | =< | >= | > | < | @< | @> | @=< | @>=

Nu exista intrari (inca) pentru literele J, K, X, Y, Z.

append
Built-in predicat append(?List1,?List2,?List1_then_List2) reuseste daca List1, urmata de List2 = List1_then_List2. Exemple:

?- append([a, b], [c, d, e], Result).
Result = [a, b, c, d, e].
true.
?- append([a, b], SecondBit, [a, b, c, d, e]).
SecondBit = [c, d, e]
true.
?- append(FirstBit, [c, d, e], [a, b, c, d, e]).
FirstBit = [a, b]
true.

O greseala incepator nu mai putin frecvente este de a folosi append([Head], Tail, List) pentru a construi o lista in loc de ceva de genul List = [Head | Tail]. Acest lucru va functiona, dar este ca cu ajutorul unui buldozer pentru a sapa o groapa pentru a planta un rasad.

Nota: exista, de asemenea, o versiune independent de append care ia un singur parametru. Acest lucru este descris in conformitate cu fisiere, si este mentionata ca append/1 - adica 1 argument, in timp ce append in acest articol este mentionat ca append/3 - 3 argumente.

arg
Nu este un strigat de frustrare la inca un alt mesaj de eroare, ci, mai degraba, o abreviere pentru argument, si, de asemenea, numele a construit-o in predicat metalogical, care extrage argumente dintr-o structura. Exemplu:

?- arg(2, buys(john, beer), Arg).
Arg = beer

De asemenea, este posibil sa se puna argumentele in ceea ce priveste utilizarea arg, ar trebui acest lucru se dovedeste util:

?- X = likes(mary, Y), arg(2, X, pizza).
X = likes(mary, pizza)
Y = pizza

argument
A se vedea arg, termen.

aritmetica
Multe dintre operatorii aritmetici uzuale sunt disponibile in Prolog:
Operator Semnificatie Exemplu
+ plus 2 is 1 + 1.
- scadere 1 is 2 – 1.
- unar minus Incercati interogarea X is 1, Y is - X.
* multiplicare 4 is 2 * 2.
/ diviziune 2 is 6 / 3.
/ / intreg diviziune 1 is 7 // 4.
Mod intreg restul 3 is 7 mod 4.
** exponentiation 1.21 is 1.1 ** 2.

Cu exceptia, in contextul unui operator de comparatie aritmetic, expresii aritmetice trebuie sa fie evaluate in mod explicit Prolog, folosind is built-in predicat.

In mare parte se foloseste acesti operatori intr-un gol mai mult ca aceasta:

X is Y + 2
in cazul in care Y este o variabila deja legat la o valoare numerica, sau poate un obiectiv compararea aritmetica ca aceasta:
X > Y * Z
Iata un alt exemplu: o regula pentru a spune daca un numar (intreg) este impar:
odd(Num) :- 1 is Num mod 2.
Un alt mod de a face aceasta este de a utiliza =:= :
odd(Num) :- Num mod 2 =:= 1.
Daca ati fi dorit sa fie mai precaut, ai putea verifica in primul rand ca Num este de fapt un numar intreg:
odd(Num) :- integer(Num), 1 is Num mod 2.

Ca de obicei in calculele digitale, cu numere fractionare, este necesar sa fie atent cu probleme de armonizare. Astfel, de exemplu finala in tabelul de mai sus, 1.21 is 1.1 ** 2. de fapt, nu reuseste atunci tastate in Prolog ca o interogare. Acest lucru se datoreaza faptului ca 1.1 ** 2, asa cum este reprezentat in computere, vine de fapt a fi ceva de genul 1.210000000001. A se vedea sectiunea privind operatorii de comparatie pentru o solutie la aceasta problema.

Retineti ca SWI Prolog face unele lucruri aparent ciudate in domeniul de aritmetica:

?- X is [a].
X = 97.

?- X is [a] + [b].
X = 195.

?- X is sqrt(23456).
X = 153.154.

?- X is sqrt([23456]).
X = 153.154.

?- X is sqrt(123456789).
X = 11111.1.

?- X is sqrt([123456789]).
X = 13.3791.
Codul ASCII pentru o este de 97, ceea ce explica un fel de primele doua rezultate de interogare. Ultima pereche de interogari sunt deosebit de ciudate. Cel mai bine este sa se evite bazandu-se pe acest tip de lucru, si stick la notatie aritmetice standard. Evitati trucuri ciudat: cod ar trebui sa fie usor de inteles.

A se vedea, de asemenea, operatorii de comparatie, functii predefinite.

aritate
Aritatea un functor este numarul de argumente este nevoie. De exemplu, aritatea likes, la fel ca in likes(jane, pizza), este de 2, ca este nevoie de doua argumente, jane si pizza.
Aritate Exemplu Ar putea sa insemne...
0 linux. un pic cum ar fi #define LINUX in * C
1 happy(fido). Fido este fericit.
2 likes(jane, pizza).
3 gave(mary, john, book). Maria a dat o carte Ioan.

* Greu de utilizat in practica in Prolog: in cazul in care codul contine linux. atunci ai putea sa testeze pentru acest lucru, dar daca nu, atunci testarea linux in codul dvs. va declansa o "procedura de nedefinite: linux / 0" eroare. Aveti posibilitatea sa lucrati in jurul valorii de acest lucru prin declararea linux care urmeaza sa fie dinamica - si anume punerea linia

:- dynamic linux/0.
in codul dvs. (de obicei la inceputul).

Fiecare fapt si de regula intr-un program Prolog, si fiecare predicat built-in are o aritatea. Deseori, acesta este mentionata in descrierile de aceste fapte si norme, prin adaugarea / si aritatea la numele statului sau de fapt. De exemplu, built-in predicat membru / 2 are aritatea 2.

Un fapt sau norma poate avea mai mult de un aritatea. De exemplu, ati putea dori sa aiba doua versiuni de make ceea ce priveste:

% make(X, Y, Z): X makes Y for Z
make(fred, chest_of_drawers, paul).
make(ken, folding_bicycle, graham).

% make(X, Y): X makes Y
make(steve, fortune).
make(kevin, mistake).
Ceea ce avem aici se make/3 si make/2.

assert, asserta, assertz
afirma este o meta-predicat care adauga argumentul sau unic, care poate fi un fapt sau o regula, la baza de date Prolog. Ideea este ca voi construi sau invata un fapt nou sau norma in curs de executare program Prolog, si doriti sa-l adaugati la baza de date. asserta asigura ca faptul adaugat / regula, se adauga inainte de orice alte fapte sau cu normele acelasi functor ), in timp ce assertz adauga faptul ca dupa orice alte norme sau fapte cu acelasi functor. Atunci cand mai mult de o regula / fapt cu acelasi functor este prezenta in baza de date, ei sunt judecati in ordinea in care ele apar in baza de date, de unde si nevoia de asserta si assertz. Tu ar folosi asserta in cazul in comun in cazul in care se presupune fapt nou pentru a salva efortul implicat in verificarea faptului utilizand reguli si alte fapte. S-ar putea folosi assertz, de exemplu, daca ati fost incercarea de a construi o structura de date coada (in cazul in care elementele sunt adaugate la sfarsitul cozii de asteptare Exemple.:

?- assert(rich(mary)).
true.

?- rich(mary).
true.

?- assert((happy(X) :- rich(X), healthy(X))).
X = _G180

?- assert(healthy(mary)).
true.

?- happy(X).
X = mary

Fapte / reguli care sunt incarcate dintr-un fisier nu poate fi amestecat cu fapte / reguli, care sunt create folosind assert / asserta / assertz fara a tine pasul speciale de declarare a procedurii in cauza sa fie dinamica. De exemplu, daca aveti o regula sa spun, calcula N, cu antet! factorial(+N, -Result), adica cu functor factorial si Arity 2, si, de asemenea, va doriti sa utilizati asserta pentru a adauga pre-calculate valorile unor factorialele la baza de date Prolog (a se vedea, de asemenea, memoisation ), atunci va trebui sa declare factorial care urmeaza sa fie dinamic, inclusiv prin urmatorul text cu normele dvs. incarcate pentru factorial :

:- dynamic factorial/2.

Programe cu assert Ed faptele si normele pot fi foarte greu pentru a depana.

Vezi de asemenea si retract, retractall, dynamic.

atom
Un atom, in Prolog, inseamna un singur element de date. Acesta poate fi de unul dintre cele patru tipuri:
  • un atom de sir de caractere, cum ar fi "Acesta este un sir", sau
  • un simbol, ca likes, john, si pizza, in likes(john, pizza). Atomii de acest tip trebuie sa inceapa cu o litera minuscula. Acestea pot include cifre (dupa initiala minuscule litera) si caracterul subliniere ( _ ).
  • lista goala []. Acesta este unul ciudat: alte liste nu sunt atomi. Daca va ganditi la un atom ca ceva care nu este divizibil in parti (sensul originar al atomului de cuvant, desi subminata de fizica subatomica), apoi [] fiind un atom este mai putin surprsing, deoarece cu siguranta nu este divizibil in parti.
  • siruri de caractere speciale, cum ar fi <--->, ..., ===>. Cand se foloseste atomi de acest tip, unele este nevoie de ingrijire pentru a evita folosirea siruri de caractere speciale, cu un sens predefinit, cum ar fi gat simbol :-, taiate simbol !, si diverse aritmetica si compararea operatorilor.
    Caracterele disponibile speciale pentru construirea aceasta clasa de atom sunt: +, -, *, /, <, >, =, :, ., &, _, si ~.

Numeri, in Prolog, nu sunt considerate a fi atomi.

atom este, de asemenea, numele unui predicat built-in, care testeaza daca argumentul sau unic este un atom.

?- atom(pizza).
true.

?- atom(likes(mary, pizza)).
false.

?- atom(<-->).
true.

?- atom(235).
false.

?- X = some_atom, atom(X).
X = some_atom.
Ultimul exemplu ce inseamna ca atom(X) a reusit, cu X legat de some_atom.

atom_chars
Built-in predicat Prolog atom_chars face conversia unui atom in lista de scrisori sale constitutive, sau vice-versa. Un concept destul de larg de atom este utilizat: acest predicat va lipici impreuna (sau divizat) orice caractere rezonabil-o dai. O lista posibila ar fi de a pune impreuna o lista de litere citit, cate un caracter la un moment dat, pentru a face un cuvant - care este, un atom al carui nume este cuvantul. Exemple:

?- atom_chars(pizza, List).
List = [p, i, z, z, a]

?- atom_chars(Atom, [b, e, e, r]).
Atom = beer

?- atom_chars(2007, List).
List = ['2', '0', '0', '7']

?- atom_chars(Atom, ['[', '3', ' ', ',', '4', ']']).
Atom = '[3 ,4]' 

A se vedea, de asemenea, atom_codes.

atom_codes
Built-in predicat Prolog atom_codes face conversia unui atom in lista de coduri numerice utilizate pe plan intern pentru a reprezenta personajele din atom, sau vice-versa. Exemple:

?- atom_codes(pizza, List).
List = [112, 105, 122, 122, 97] 

?- atom_codes(Atom, [98, 101, 101, 114]). 
Atom = beer 

A se vedea, de asemenea, atom_chars.

backtracking
Backtracking este de fapt o forma de cautare. In contextul de Prolog, sa presupunem ca interpretul Prolog incearca sa satisfaca o secventa de goluri goal_1, goal_2. In cazul in care interpretul Prolog gaseste un set de variabile legaturi care permit goal_1 sa fie indeplinite, ea se angajeaza la aceste legaturi, si apoi incearca sa satisfaca goal_2. In cele din urma unul din doua lucruri se intampla: (a) goal_2 este indeplinita si terminat cu, sau (b) goal_2 nu pot fi satisfacute. In ambele cazuri, backtracks Prolog. Asta este, "ne-angajeaza" sa se legaturi variabila a facut in satisfacerea goal_1 si merge in cautarea unui alt set de variabile care permit legaturi goal_1 care urmeaza sa fie indeplinite. Daca gaseste un al doilea set de astfel de legaturi, se angajeaza sa le si veniturile pentru a incerca sa satisfaca goal_2 din nou, cu legaturi noi. In cazul in care (a), interpretul Prolog este in cautarea de solutii suplimentare, in timp ce in cazul (b) este inca in cautarea pentru prima solutie. Deci, backtracking pot servi pentru a gasi solutii suplimentare pentru o problema, sau sa continue cautarea pentru o solutie in primul rand, atunci cand un prim set de ipoteze (de exemplu legaturi variabila) se dovedeste a nu sa duca la o solutie.

Exemplu: aici este definitia built-in predicat Prolog member :

member(X, [X | Rest]). % X is a member if its the first element
member(X, [Y | Rest]) :-
    member(X, Rest).   % otherwise, check if X is in the Rest
Nu aveti dreptul sa cred ca de member ca un predicat backtracking, dar backtracking este construit in Prolog, deci in conditii adecvate, member vor cale intoarsa:
?- member(X, [a, b, c]).
X = a ;
X = b ;
X = c ;
false.
Aici member backtracks pentru a gasi orice solutie posibila interogarea dat sa-l. Luati in considerare, de asemenea:
?- member(X, [a, a, a]).
X = a ;
X = a ;
X = a ;
false.
Aici member backtracks, chiar daca pastreaza pe gasirea acelasi raspuns. Ce zici de
?- member(a, [a, a, a]).
true ;
true ;
true ;
false.
Acest lucru se datoreaza faptului ca Prolog are trei moduri de a dovedi ca a este un membru al [a, a, a].

Backtracking termen lung, de asemenea, trebuie sa cauti mai multe seturi de legaturi variabila pentru a satisface un singur gol.

In anumite circumstante, ar putea fi de dorit sa se inhiba backtracking, ca atunci cand doar o singura solutie este necesara. Prolog taiat Scopul permite acest lucru.

Tracing executarea de o bucata de cod Prolog care backtracks poate fi o modalitate buna pentru a afla ce se intampla in timpul backtracking. Daca ati fi dorit sa experimenteze cu backtracking prin trasarea member, ai putea realiza acest lucru prin copierea codului de member, avand in vedere mai sus, schimbarea numelui de member sa spun mem in cele trei locuri unde se pare, si apoi urmarirea dvs. mem procedura.

bagof
Built-in predicat bagof(+Template, +Goal, -Bag) este utilizat pentru a colecta o lista Bag a tuturor elementelor Template care indeplinesc un scop Goal. Exemplu: presupunem

likes(mary, pizza).
likes(marco, pizza).
likes(Human, pizza) :- italian(Human).
italian(marco).
Apoi
?- bagof(Person, likes(Person, pizza), Bag).
Person = _G180
Bag = [mary, marco, marco]

Observati ca Bag contine elementul marco de doua ori, pentru ca exista doua modalitati de a dovedi ca marco place pizza -. fapt si prin intermediul regula bagof esueaza daca Goal nu are solutii.

A se vedea, de asemenea, setof, si, pentru diferentele intre bagof si findall, a se vedea findall.

obligatoriu
Legarea este un cuvant folosit pentru a descrie da o valoare intr-o variabila. In mod normal are loc in timpul aplicarii unei reguli Prolog, sau o incercare de a satisface goluri intr-un Prolog interogare.

Sa presupunem ca baza de date Prolog contine doar faptul unica likes(mary, pizza). si ca exista o interogare:

?- likes(mary, What).

Prolog va cauta in baza de date (foarte mici), constata ca interogarea poate fi indeplineste daca What = pizza, nu-l va lega What sa pizza succes si sa raporteze:

?- likes(mary, What).
What = pizza ;
false.

Acum, sa presupunem ca exista o regula si fapte in baza de date Prolog:

teaches(Teacher, Student):-
    lectures(Teacher, Subject), studies(Student, Subject).
lectures(codd, databases).
studies(fiona, databases).
studies(fred, databases).

si ca ghidul de problemele interogare:

?- teaches(codd, Who).

Interpretul Prolog primele meciuri seful statului cu interogarea, si se leaga atat de Teacher la codd. El gaseste apoi un fapt care indica faptul ca un subiect prelegeri Codd - si anume lectures(codd, databases). In acest moment, variabila Subject este legat de databases ( Subject = databases ). Cu alte cuvinte, Subject, probabil temporar, are valoarea databases. Apoi, Prolog incearca sa satisfaca de-al doilea scop studies(Student, Subject) cu Subject = databases, adica incearca sa satisfaca studies(Student, databases). Atunci cand gaseste solutia, studies(fiona, databases) se va lega Subject la fiona, si sa raporteze solutia:

?- teaches(codd, Who).
Who = fiona

Observati ca legarea Subject = databases a fost facuta in rezolvarea interogare, dar aceasta nu este raportat, deoarece nu este in mod explicit parte a interogarii.

Apoi, in cazul in care utilizatorul tasteaza " ;", Prolog va revina si anula obligatoriu Student = fiona si pentru a cauta o alta valoare pentru Subject ca indeplineste studies(Student, databases), precum si pentru a gasi Student = fred. Cu toate acestea, desi sunt obligatorii (si desfacere) este implicat in aceasta etapa, este tratat corespunzator sub backtracking.

corp
ultima parte a unei Prolog regula. Acesta este separat de cap de gat simbolul, scrise ca :-. Ea are forma unei liste separate prin virgula de obiective, fiecare dintre care este un functor, eventual urmata de o lista separata prin virgula de argumente, in paranteze. De exemplu, in regula
sister_of(X,Y) :- female(Y), X \== Y, same_parents(X,Y).
cele trei goluri female(Y), X \== Y, same_parents(X,Y) forma corpului.

built-in predicat
Pentru a face programare Prolog mai practice, un numar de predicate sau sunt construite in Prolog. Acestea includ unele proceduri de utilitate, care ar fi putut fi programate de catre utilizator Prolog, si unele care fac lucruri non-logica de programare, cum ar fi de intrare si de iesire rutine, rutine depanare, si o serie de alte persoane.

Bratko
Acest lucru se refera la textul utilizat in COMP9414/9814 de la Universitatea din New South Wales, Australia:
Bratko, I., de programare in Prolog pentru Inteligenta Artificiala, Editia a 4, Addison-Wesley, 2011

built-in functii, abs, atan, ceiling, cos, exp, float, floor, log, round, sign, sin, sqrt, tan, truncate
Un numar mic de functii matematice sunt construite in Prolog, inclusiv:

Functie Semnificatie
abs(Exp) Valoarea absoluta a Exp: Exp adica daca Exp? 0, daca-Exp Exp <0
atan(Exp) arctangenta (tangentei inversa) de Exp: Rezultatul este in radiani
cos(Exp) cosinus de Exp: Exp este in radiani
exp(Exp) Exp e: e este 2.71828182845...
log(Exp) logaritmul natural al Exp: logaritmului si anume la baza * e
sin(Exp) sinusul Exp: Exp este in radiani
sqrt(Exp) radacina patrata a Exp
tan(Exp) tangenta Exp: Exp este in radiani
sign(Exp) semn (+1 sau -1) din Exp: semnul (-3) = -1 = sign (-3.7)
float(Exp) float de Exp: float (22) = 22.0 - a se vedea, de asemenea, float predicat
floor(Exp) cel mai mare numar intreg? Exp: podea (1.66) = 1
truncate(Exp) elimina o parte fractionara a Exp: trunchia (-1.5) = -1, trunchia (1,5) = 1
round(Exp) Exp runda la cea mai apropiata numar intreg: rotund (1.6) = 2, a runda (1.3) = 1
ceiling(Exp) cel mai mic numar intreg? Exp: plafon (1.3) = 2

Aceste functii ar trebui sa fie utilizate intr-un context in care acestea vor fi evaluate de fapt, cum ar fi urmatorul text is sau ca parte dintr-o aritmetica operator de comparatie precum =:= sau >.

Exemplu:

?- X is sqrt(2).
X = 1.41421 
Comparati acest lucru cu urmatorul text, in cazul in care sqrt (2) nu este evaluat, deoarece = nu evalueaza argumentele sale.
?- X = sqrt(2).
X = sqrt(2) 

Un alt exemplu:
?- X is log(3+2).
X = 1.60944.

Aceste functii matematice poate corespunde aritate 2 predicate built-in: de exemplu, se poate face acest lucru:

?- sqrt(2, X).
X = 1.41421
Unele versiuni de SWI Prolog (de exemplu, 5.6.47) pune in aplicare multe dintre aceste aritate 2 predicate, dar nu de exemplu, exp/2.

* Liceul de Matematica Serviciul memento: daca doriti logaritmul in baza o, divide log (Exp) de log (a). De exemplu, log 10 (x) = log (X) / log (10), si log 2 (X) = log (X) / log (2).

call
call este un built-in meta-predicat, care permite argumentul sau unic de a fi numit / invocat ca un obiectiv. De exemplu, un program ar putea crea un gol (probabil folosind =.. ) cu privire la zbor, si apoi, probabil mai tarziu in program, necesitatea de a testa obiectivul. Aici sunt interogari care efectua aceste roluri - intr-un program real, atat assert si call va fi construit in procedurile Prolog scrise de catre programator.
?- assert(likes(mary, pizza)).

?- call(likes(Person, pizza)).
Person = mary

?- Goal =.. [likes, mary, What], call(Goal).
Goal = likes(mary, pizza)
What = pizza

clauza
O clauza in Prolog este o unitate de informatii intr-un program Prolog se termina cu un punct (" . "). O clauza poate fi un fapt, cum ar fi:

likes(mary, pizza).
food(pizza).

sau o regula, cum ar fi:

eats(Person, Thing) :- likes(Person, Thing), food(Thing).

O clauza poate fi, de asemenea, o interogare pentru a interpretului Prolog, la fel ca in:

?- eats(mary, pizza).

Un grup de clauze cu privire la aceeasi relatie este numita procedura.

comentand codul
In Prolog, un inceput de un comentariu este semnalizata cu caracterul %. Comentariile sunt ignorate de catre interpret Prolog, scopul lor este de a ajuta un cititor uman sa inteleaga codul Prolog. Exemple:

% This is a full line comment.
% The next line contains a part-line comment.
member(Item, [Item|Rest]). % member succeeds if Item is 1st object in list.

Orientarile Comentand

Ca si in alte limbaje de programare, comentariile ar trebui sa fie utilizate in mod liber pentru a explica semnificatia la nivel inalt de sectiuni de cod, pentru a explica sectiuni complicat de cod, etc Comentariile nu ar trebui sa ecou ceea ce codul deja spune clar. Comentariile de genul asta ajunge de fapt in calea de intelegere, de exemplu, deoarece acestea sunt susceptibile de a face pe cititor ignora comentariile. In cazul in care este posibil sa se faca inteles de cod cu ajutorul unui semnificative functor numele sau variabila nume, acest lucru este de preferat un comentariu.

Este o practica buna pentru a incepe fiecare procedura Prolog cu un comentariu care descrie ceea ce face, de exemplu,

% member(Item, List) - succeeds if the item is a member of the list

In cazul in care lista trebuie sa aiba unele proprietati speciale, de exemplu, in cazul in care trebuie sa fie o lista de numere, sau trebuie sa fie instantiat (care este, au o valoare), in momentul in care procedura se numeste, atunci acest comentariu antet ar trebui sa spun asa:

% member(Item, List) - succeeds if the item is a member of the list;
%   List must be instantiated at the time member is called. Item need not
%   be instantiated.

Acesta poate fi o idee buna pentru comentariile antet pentru a indica exemple de tipul de date pe care procedura este destinat sa functioneze, si ce rezultat ar trebui sa fie, daca acest lucru poate fi realizat in mod rezonabil pentru scurt timp. De exemplu,

% Examples of use:
% ?- member(b, [a, b, c]).
% true.
% 
% ?- member(X, [a, b, c]).
% X = a ;
% X = b ;
% X = c ;
% false.

Fiecare fisier de cod Prolog ar trebui sa inceapa cu un comentariu antet (fisier), indicand care a scris codul, atunci cand, si ceea ce este (in ansamblu) intentioneaza sa faca. Acest lucru ar fi de ajuns intr-o misiune Prolog scurt. Intr-un sistem de "rezistenta industrial" Prolog, nu ar exista detalii cu privire la originile de algoritmi folosit, si o istorie revizuire.

O buna sursa de exemple de Prolog este comentarea exemplu codul puse la dispozitie in clasa, cum ar fi aceasta. Notati, totusi, ca aceasta este mai degraba mai comentat foarte intens decat de obicei, in scopuri de instruire. Retineti, de asemenea, ca a prezentat exemple de cod de pe ecran pot fi sub-comentat, din cauza dificultatii de montare comentariile si codul de pe ecran, si pentru ca prezentarea orala de insotire a materialelor de pe ecran inlocuieste comentariile intr-o anumita masura.

Nu face liniile de comentarii (sau codul) prea mult timp - linii lungi poate fi greu de citit, si linii foarte lungi pot fi indoite, de cotitura formatarea tau ingrijit intr-un mic dejun cainelui. Stick la o lungime linia de grad maxim de 70 sau 80 de caractere. Cute linii si / sau cutii construite de caractere in comentariu au efect secundar de a impiedica cititorul sa vada cat mai mult de cod la un moment dat. Cititorul poate avea apoi la pagina in sus si in jos pentru a afla ce codul dvs. nu. Ei nu va va place pentru aceasta.

Utilizarea de bucati in mod normal, ar trebui sa fie comentate sa explice de ce este necesara taiat.

Este o idee proasta pentru a comenta (aproape) fiecare linie, in parte din cauza dezordine, si ca aceasta cauzeaza distragere, si, partial, pentru ca cele mai multe astfel de comentarii sunt inutile duplicari de cod (si / sau in comentariu lucruri evidente, cu exceptia Prolog la o novice programator):

Exemplu de Bad comentand (fiecare linie de comentat):

factorial(0, 1).                     % Factorial of 0 is 1.
factorial(N, FactN) :-
    N > 0,                           % N is positive
    Nminus1 is N - 1,                % Calculate N minus 1
    factorial(Nminus1, FactNminus1), % recursion
    FactN is N * FactNminus1.        % N! = N * (N - 1)!
Dintre aceste comentarii, doar prima si ultima sunt chiar slab justificate, si chiar si acestea sunt, probabil, prea evident, ca, mai ales pentru ultimul comentariu, numele variabilei sa va spun tot ce ai nevoie sa stii. Se pare destul, cu toate % semnele-frumos aliniate, dar fortele de cititor pentru a verifica prin toate comentariile inutile in cazul in care exista nimic important acolo. Acest cod are nevoie de un comentariu antet procedura, si, probabil, nimic altceva, desi un programator Prolog inceput ar putea fi justificata in subliniind faptul ca linia N > 0, este acolo pentru a va asigura ca regula este utilizata numai in cazul in care N este pozitiv. (Daca nu sunteti sigur de ce acest lucru este atat de important, incercati sa lasati afara N > 0, si de testare privind functia spune N = 2.) Deci in comentariu ar fi " % only use rule if N > 0. "

Cum de a scrie comentarii si mai rau!

Este usor - doar scrie comentarii care sunt de fapt gresite. trist se confrunta cu
Opinie comentariile dvs. intr-un moment rece, si asigurati-va ca ceea ce spun ei este adevarat.

+ -? conventie pentru procedurile de argumente pentru a

O conventie adesea utilizate pentru a face rolul de argumente intr-o procedura mai clara este de a le eticheta cu +, , si ?, dupa cum urmeaza:

Eticheta Semnificatie
+ Argumentul este de asteptat sa fie instantiat (de exemplu, au o valoare mai degraba decat sa fie o variabila) in cazul in care procedura se numeste ca un scop.
argument este de asteptat sa fie o variabila de a fi legat in cazul in care procedura se numeste ca un scop.
? argument poate fi instantiata, sau poate fi o variabila nelegat, in cazul in care procedura se numeste ca un scop.

Exemplu:

% factorial(+N, -FactorialN).
%% supply a value for N, and FactorialN will be computed.

% member(?Item, ?List).
%% Item and List may either be instantiated, or a variable
%% (but in fact at least one of them must be instantiated!)
Merita verificarea, apropo, ce se intampla daca List nu este instantiat...
?- member(a, List).

List = [a|_G231] ;

List = [_G230, a|_G234] ;

List = [_G230, _G233, a|_G237] 
si asa mai departe... Prolog fabrica drum prin toate structurile lista care contin a.

Ortografie, gramatica, etc

Nu este nici un lucru rau, daca toate aceste comentarii sunt scrise corect gramatical si sunt formulate. (Uneori este necesar sa se abrevierea, asa ca, probabil comentariile dvs. nu toate trebuie sa fie Exemple de plin.) Aceasta face viata mai greu pentru oameni incercarea de a citi codul, in cazul in care trebuie sa Wade prin ortografie sarace si gramatica. Amintiti-va ca oameni care citesc codul de dvs. va include persoanele pe care vor dori sa inteleaga comentariile dvs. cu usurinta - ajutoare, markere, colegii, seful tau, chiar va in timp de un an de cand ati uitat cum ai ajuns codul pentru a lucra... Asa ca in bune obiceiuri comentand de la inceput.

A se vedea, de asemenea, indentarea si spatiu alb.

Compara operatorii
(. Numai unele dintre operatorii de mai jos sunt relevante pentru COMP9414 la Universitatea din New South Wales - a se vedea de colorat verde de mai jos) Prolog are doua clase principale de operatorii de comparatie - operatorii de comparatie aritmetica (si similare operatori alfabetice comparatie) si unificarea stil-operatorii:

Comparatie Definitie Evalueaza?
X = Y reuseste daca X si Y unifica (meci), in sensul Prolog Nu
X \= Y reuseste daca X si Y nu unifica, adica daca not (X = Y) Nu
T1 == T2 daca reuseste termeni T1 si T2 sunt identice; de??exemplu, numele de variabile trebuie sa fie aceeasi Nu
T1 \== T2 daca reuseste termeni T1 si T2 nu sunt identice Nu
E1 =:= E2 reuseste daca valorile expresii E1 si E2 sunt egale Da
E1 =\= E2 reuseste daca valorile expresii E1 si E2 nu sunt egale Da
E1 < E2 reuseste daca valoarea numerica a expresiei E1 este <valoarea numerica a E2 Da
E1 =< E2 reuseste daca valoarea numerica a expresiei E1 este? valoarea numerica a E2 Da
E1 > E2 reuseste daca valoarea numerica a expresiei E1 este> valoarea numerica a E2 Da
E1 >= E2 reuseste daca valoarea numerica a expresiei E1 este? valoarea numerica a E2 Da
T1 @< T2 reuseste daca T1 este in ordine alfabetica <T2 Nu
T1 @=< T2 reuseste daca T1 este in ordine alfabetica? T2 Nu
T1 @> T2 reuseste daca T1 este in ordine alfabetica> T2 Nu
T1 @>= T2 reuseste daca T1 este in ordine alfabetica? T2 Nu

A se vedea, de asemenea, is. is nu este un operator de comparatie, dar este adesea confundat cu = de catre programatorii Prolog novice. Pe scurt, utilizati X is Exp pentru a evalua o expresie aritmetica, cum ar fi Y + 2, care contine un operator aritmetic, cum ar fi +, si se leaga valoarea rezultata la variabila X la stanga a operatorului is.

Ca un exemplu de @< si rudele sale,

?- likes(mary, pizza) @< likes(mary, plums).
true.
Acest lucru reuseste pentru ca likes si mary sunt aceleasi, atat in termeni, si pizza in ordine alfabetica precede plums.

Comparatie de numere fractionare: Cand se compara doua numere fractionare, pot aparea probleme de natura aproximative de reprezentari de numere fractionare in computere. Uneori, acesta va lucra ca de asteptat, si, uneori, nu. De exemplu, interogarea 1.21 =:= 1.1 * 1.1. esueaza cu SWI Prolog pe calculator in cazul in care acest articol a fost scris. Puteti si ar trebui sa functioneze in jurul valorii de aceasta problema de catre, in loc de testare numere fractionare pentru egalitatea de sanse, face ceva de genul urmator:

?- abs(1.21 - 1.1 * 1.1) < 0.000001.
true.
abs inseamna "valoare absoluta": abs(X) = X daca X >= 0 si abs(X) = -X daca X =< 0.
Mai mult, in general, de testare pentru abs(X - Y) < Tiny, in cazul in care Tiny este obligat sa numar mic (sau este un numar mic, ca in exemplul). Cat de mica pentru a face Tiny de mai sus depinde de la caz la caz - va trebui sa utilizati un numar mai mic in cazul in care X si Y trebuie sa fie foarte aproape impreuna pentru a face munca algoritm corect.

consult
Aceste pre-definite pseudo-predicate permite o pentru a incarca cod Prolog intr-un interpret Prolog executa. Exemplu:
?- consult('myprogram.pl').
Aceasta incarca continutul programului Prolog in fisierul myprogram.pl in baza de date Prolog executa lui. Retineti ca, in SWI Prolog, cel putin, inainte de a incarca noile fapte si norme in baza de date, Prolog elimina primul toate faptele si normele care se refera la procedurilor in myprogram.pl. Deci, daca myprogram.pl contine, de exemplu, faptul likes(jane, pizza) apoi toate faptele si normele cu privire la likes, care au doua argumente vor fi sterse din baza de date Prolog inainte de fapte noi in myprogram.pl sunt incarcate in sus. Acest lucru este convenabil atunci cand sunt utilizati consult pentru a re-incarcati un program de editare dupa aceasta (de exemplu, intr-o alta fereastra, cu interpretul Prolog stanga de functionare), dar ar putea fi un pic surprinzator daca ati fost incercarea de a incarca fapte suplimentare dintr-un fisier.

Este posibil sa se consulte mai mult de un fisier la un moment dat, prin inlocuirea numele singur fisier cu o lista de fisiere:

?- consult(['file1.pl', 'file2.pl', 'file3.pl']).
% file1.pl compiled 0.00 sec, 524 bytes
% file2.pl compiled 0.01 sec, 528 bytes
% file3.pl compiled 0.00 sec, 524 bytes
true.
De asemenea, este posibil sa se consulte abrevierea un apel, pur si simplu tastati lista de (unul sau mai multe), fisiere ca un obiectiv pentru Prolog:
?- ['file1.pl', 'file2.pl', 'file3.pl'].
In unele implementari Prolog, consultarea user cauze interpretului Prolog pentru a citi faptele si normele de terminal al utilizatorului in:
?- [user].
|: likes(jane, pizza).
|: bad_dog(Dog) :-
|:    bites(Dog, Person),
|:    is_human(Person),
|:    is_dog(Dog).
|: <control-D>
% user://1 compiled 0.00 sec, 1,156 bytes
true.
?- 

curentul de intrare fluxul
La un moment dat, contributia la Prolog vine de la "fluxul de intrare curent". Atunci cand Prolog porneste, fluxul de intrare curent este tastatura de calculator / statie de lucru de la care Prolog a fost pornit.

Cu toate acestea, s-ar putea dori pentru a obtine de intrare / citire de la alta parte in timpul executarii programului Prolog dvs. - de exemplu, ati putea dori sa citeasca dintr-un fisier a avut loc pe computerul pe care programul se executa, sau pe un server local de fisiere. Pentru a schimba fluxul de intrare curent, utilizati Prolog built-in extra-logic predicat see. Daca Prolog executa gol see('input.dat'), atunci va veni ulterior de intrare din fisierul input.dat, in directorul curent de lucru a * statia de lucru care se executa Prolog. Daca fisierul specificat nu poate fi gasit in directorul de lucru curent, o eroare pot fi raportate, ca si in aceasta interactiune cu SWI Prolog:

?- see('nosuchfile.dat').
ERROR: see/1: source_sink `nosuchfile.dat' does not exist (No such file or directory)

Alte erori sunt posibile - ar putea sa nu aiba dreptul de a citi dosarul in cauza, de exemplu. Daca fisierul nu exista si este usor de citit, apoi operatiunile ulterioare citi obtine date de la dosar. Parametru pentru a see poate fi doar numele de fisier, cum este ilustrat mai sus, sau ar putea fi o cale spre fisierul care este dorit: de exemplu, see('/Users/billw/prologstuff/input.dat') Prolog va continua sa emita solicitari pentru mai multe interogari in timp ce se "vede" un fisier, dar toate operatiile explicit citire a accesa fisierul. Built-in extra-logice predicat seen (cu nici un argument) va permite sa reveniti la citirea datelor de la tastatura. Exemplu (presupunand info.dat incepe cu linia de hungry(jack). ):

?- see('info.dat'), read(X).
X = hungry(jack)

?- seen, read(Y).
|: full(jack).
Y = full(jack)

A se vedea, de asemenea, fluxul de iesire curent, intrare, iesire, fisierele.

* Strict vorbind, input.dat va fi de asteptat sa fie in directorul de lucru curent de interpretorul de comenzi, care a inceput Prolog. Interpretor de comenzi vor fi difuzate pe statia de lucru / calculator, si trimiterea de iesire intr-o fereastra pe care statie de lucru sau calculator.

fluxului de curent de iesire
La un moment dat, de intrare pentru a merge la Prolog "stream curent de iesire". Atunci cand Prolog porneste, fluxul de curent de iesire este fereastra sau consola de statii de lucru calculatorul / de la care Prolog a fost pornit. Cu alte cuvinte, atunci cand programul scrie lucruri folosind predicatele descrise in articol pe scris, acestea apar pe ecran.

Cu toate acestea, ati putea dori sa scrie in alta parte in timpul executarii programului Prolog dvs. - de exemplu, ati putea dori sa scrie intr-un fisier a avut loc pe computerul pe care programul se executa, sau pe un server local de fisiere.

Pentru a schimba fluxul curent de iesire, utilizati una dintre Prolog built-in extra-logice predicate tell si append/1 *. Daca Prolog executa obiectivul tell('output.dat'), apoi de iesire va merge ulterior la dosar output.dat, in directorul curent de lucru a * statia de lucru care se executa Prolog.

Daca fisierul specificat nu poate fi gasit in directorul de lucru curent, acesta va fi creat. Daca fisierul nu exista, acesta va fi suprascris. Daca utilizati append/1, operatiunile ulterioare a scrie va adauga material la sfarsitul fisierului, in loc de a suprascrie fisierul. Daca nu aveti permisiunea de a scrie fisiere in directorul curent, veti vedea un mesaj de eroare:

?- tell('/usr/bin/ztrash').  
ERROR: tell/1: No permission to open source_sink `/usr/bin/ztrash' (Permission denied)

Acest lucru inseamna ca fie nu aveti permisiunea de a scrie fisiere in directorul /usr/bin, sau daca fisierul ztrash exista deja in acest director, ca nu aveti permisiunea de a scrie in acest fisier.

In cazul in care fisierul este in masura sa fie scris, apoi operatiunile ulterioare a scrie trimite datele lor de la dosar. Parametrul de a tell poate fi o cale catre fisier care este dorit, ca in exemplul de mai sus, sau ar putea fi doar numele de fisier, de exemplu, tell('output.dat'). Prolog va continua sa emita solicita pentru mai multe interogari si legaturi de imprimare in timp ce sunt "spune" sau "adaugarea" un fisier, dar toate operatiile explicit scriere a accesa fisierul. Built-in extra-logice predicat told (cu nici un argument) va permite sa reveniti la scrierea de date de fereastra originala. Exemplu:

?- tell('info.dat'), write(thirsty(jack)), nl.
true.
?- told, write(drunk(jack)).
drunk(jack)
true.
?- halt.
% cat info.dat # - # is Unix comment char, cat lists info.dat
thirsty(jack)
% 

A se vedea, de asemenea, fluxul de intrare curent, de intrare, iesire, fisierele.

* append/1 nu este legat de append/3, care, la randul sau, nu are nimic de-a face cu fluxuri de iesire.

# Strict vorbind, output.dat va fi de asteptat sa fie in directorul de lucru curent de interpretorul de comenzi, care a inceput Prolog. Interpretor de comenzi vor fi difuzate pe statia de lucru / calculator, si trimiterea de iesire intr-o fereastra pe care statie de lucru sau calculator.

taiate,!
Taiat, in Prolog, este un obiectiv, scris ca !, care reuseste mereu, dar nu poate fi regresat trecut. Este utilizat pentru a preveni backtracking nedorite, de exemplu, pentru a preveni solutii de suplimentare a fost gasit de catre Prolog.
Taietura trebuie sa fie folosit cu economie. Exista o tentatie de a introduce reduceri experimental intr-un cod care nu functioneaza corect. Daca veti face acest lucru, tineti minte ca atunci cand depanare este complet, ar trebui sa inteleaga efectul, si sa fie capabili sa explice necesitatea, fiecare taiat utilizati. Utilizarea unei reduceri ar trebui sa fie, astfel, comentate.

Exemplu: Sa presupunem ca avem urmatoarele fapte:

teaches(dr_fred, history).
teaches(dr_fred, english).
teaches(dr_fred, drama).
teaches(dr_fiona, physics).
studies(alice, english).
studies(angus, english).
studies(amelia, drama).
studies(alex, physics).

Apoi ia in considerare urmatoarele interogari si iesirile lor:

?- teaches(dr_fred, Course), studies(Student, Course).

Course = english
Student = alice ;

Course = english
Student = angus ;

Course = drama
Student = amelia ;

false.

Backtracking nu este inhibata aici. Course este initial legat de history, dar nu exista elevi de history, astfel incat obiectivele doilea esueaza, backtracking apare, Course este re-legat de english, al doilea scop este de incercat si de cele doua solutii gasite ( alice si angus ), apoi backtracking se produce din nou, si Course este legat de drama, si o finala Student, amelia, se gaseste.

?- teaches(dr_fred, Course), !, studies(Student, Course).

false.

Acest timp Course este initial legat de history, atunci scopul taiat este executat, iar apoi studies Scopul este incercat si nu reuseste (pentru ca nimeni nu studies history ). Din cauza taiate, nu putem sa revina teaches scopul de a gasi un alt caracter obligatoriu pentru Course, astfel incat interogarea intreg esueaza.

?- teaches(dr_fred, Course), studies(Student, Course), !.

Course = english
Student = alice ;

false.

Aici teaches scopul este incercat ca de obicei, si Course este legat de history, din nou, ca de obicei. Inainte studies obiectivul este incercat si nu reuseste, astfel incat noi sa nu ajungem la reducerea de la sfarsitul interogare de la acest punct, si backtracking pot aparea. Astfel, teaches scopul este re-incercat, si a Course este obligata sa english. Apoi studies Scopul este incercat din nou, si reuseste, cu Student = alice. Dupa aceea, obiectivul este de taiat incercat si, desigur, reuseste, astfel incat nu mai este posibila revenire si doar o singura solutie este astfel gasit.

?- !, teaches(dr_fred, Course), studies(Student, Course).

Course = english
Student = alice ;

Course = english
Student = angus ;

Course = drama
Student = amelia ;

false.
?- 

In acest ultim exemplu, aceleasi solutii se gasesc ca in cazul in care nu a fost prezenta taiat, pentru ca niciodata nu este necesar sa se faca cale intoarsa trecut taiat pentru a gasi urmatoarea solutie, astfel incat backtracking nu este inhibata.

Bucati in Regulamentul

In practica, reducerea este utilizat in normele, mai degraba decat in??multi-scop interogari, si unele expresii idiomatice special, se aplica in astfel de cazuri. De exemplu, luati in considerare codul de mai jos pentru max(X, Y, Max), care se presupune de a lega Max cu cel mai mare de X si Y (care se presupune a fi numere).

max(X, Y, X) :- X > Y, !.
max(X, Y, Y).
Aceasta este o modalitate de a spune: "in cazul in care prima regula reuseste, utilizare si nu incercati doua regula (In caz contrar, utilizeaza doua regula.) Am fi putut avea loc in scris.:
max(X, Y, X) :- X > Y.
max(X, Y, Y) :- X =< Y.
caz in care atat norme va fi in mod normal, a incercat (cu exceptia cazului in backtracking este impiedicata de o reducere, in unele alta parte a codului). Aceasta cifra este usor mai putin eficienta in cazul in care X este, de fapt, mai mare decat Y (backtracking inutile apare), dar mai usor pentru oameni sa inteleaga, desi programatori regulat Prolog rapid ajunge sa recunoasca acest tip de idiom. Calculul suplimentare, in cazul de max este triviala, dar, in cazurile in care doua regula implica un calcul lung, ar putea fi un argument puternic pentru utilizarea taiat din motive de eficienta.

depanare
inseamna eliminarea erorilor din codul programului. Acest lucru se face prin (1) respectarea erori (de exemplu, testare ), (2) localizarea cauzei in cod; (3) corectarea erorilor.

(1) si (2) sunt de multe ori partea cea mai grea. Odata ce ati observat sau detectat o eroare, urmarire codul in cauza poate ajuta la descoperirea problemei. Uneori inserarea invita sa write in parti de cod in cazul in care credeti ca problema ar putea fi poate ajuta pentru a localiza eroarea.

In cele din urma, codul de lectura dvs. cu atentie si vor fi parte din sarcina. Asa ca ar fi o idee buna pentru a scrie codul cu atentie in loc primul rand, in scopul de a face mai usor de inteles. A se vedea, de asemenea, de eroare si mesajele de avertizare si comentarea si spatiu alb.

declarativ
Un limbaj de programare declarativ este una in care relatiile dintre date sunt indicate (sau a declarat intr-o limba (de obicei, bazate pe logica), iar apoi un mecanism automat, de exemplu, o teorema-demonstratorului, este utilizat pentru a raspunde intrebarilor cu privire la date. Prolog este un limbaj de programare declarativ. Haskell, Miranda, Lisp, si sistemul sunt limbajele functionale de programare, in care toate constructiile sunt exprimate folosind functii, argumente de functii, si rezultatele functia, si C, C + +, Java, Perl, Pascal, Modula-2, si Fortran sunt exemple de (la nivel inalt) limbile procedurale de programare, in care a codului de program isi exprima procedurile de urmat in manipularea datelor.

dynamic
In Prolog, o procedura este fie statice sau dinamice. O procedura statica este unul al carui fapte / reguli sunt predefinite la inceputul de executare, si nu se schimba in timpul executiei. In mod normal, faptelor / reguli vor fi intr-un fisier de cod Prolog care vor fi incarcate in timpul sesiunii Prolog. Uneori, este posibil sa doriti sa adaugati fapte suplimentare (sau poate chiar normele suplimentara) la procedura, in timpul executarii unei interogari Prolog, folosind assert / asserta / assertz ", sau poate elimina faptelor / normelor folosind retract / retractall. Pentru a face acest lucru, trebuie sa declare procedura sa fie dinamica.

Puteti declara o procedura care urmeaza sa fie dinamica, prin includerea in codul de utilizator (in mod normal, in apropierea faptelor / normele pentru aceasta procedura) un sistem corespunzator de dynamic directiva. Exemplu - sa presupunem ca aveti o procedura numita likes, cu aritate 2 si aveti un "set pentru incepatori" de fapte / normelor in program Prolog dumneavoastra, dar doriti sa deduce fapte suplimentare despre likes in timpul executiei, si adaugati-le la baza de date, astfel incat nu au nevoie sa fie recalculate de fiecare data cand acestea sunt utilizate. [Tu ar fi in mod normal, face acest lucru doar - adaugati fapte noi la baza de date - in cazul in care faptele au fost lente in plus pentru a calcula.] Ai nevoie de a declara likes (cu aritate 2) sa fie dinamica. Poti face acest lucru, dupa cum urmeaza:

:- dynamic likes/2.

[Apropo, observati ca aceasta lasa deschisa posibilitatea ca o versiune diferita a likes (cu aritate 3, spune), ar putea sa nu fie dinamica.]

A se vedea, de asemenea, memoisation.

eficienta
Exista multe modalitati de cod care urmeaza sa fie ineficiente. Acest articol se concentreaza pe problema de a evita inutile apeluri recursive. Luati in considerare urmatorul exercitiu: a scrie un predicat Prolog printOrAdd(IntegerList, Sum) care se leaga numerele chiar din lista sa de intrare IntegerList la o lista EvensList, si in acelasi timp, se adauga pana numere impare in IntegerList si leaga-le la Sum. Aici sunt doua versiuni ale codului, printOrAdd si printOrAdd1 :
% printOrAdd is an inefficient solution to the task posed above:

printOrAdd([], [], 0).

% even numbers
printOrAdd([First | Rest], [First | RestOfEvens], Sum) :-
  printOrAdd(Rest, RestOfEvens, Sum),
  0 is First mod 2.

% odd numbers
printOrAdd([First | Rest], RestOfEvens, Sum) :-

  printOrAdd(Rest, RestOfEvens, SumOfRest),
  1 is First mod 2,
  Sum is SumOfRest + First.

% printOrAdd1 is a corrected version of printOrAdd which
% avoids the unnecessary recursive calls.

printOrAdd1([], [], 0).

printOrAdd1([First | Rest], [First | RestOfEvens], Sum) :-
  0 is First mod 2,
  printOrAdd1(Rest, RestOfEvens, Sum).

printOrAdd1([First | Rest], RestOfEvens, Sum) :-
  1 is First mod 2,
  printOrAdd1(Rest, RestOfEvens, SumOfRest),
  Sum is SumOfRest + First.

?- printOrAdd([1,2,3,4,5,6], Evens, SumOfOdds).
Evens = [2, 4, 6],
SumOfOdds = 9 ;
false.

Prima versiune a face apel recursiv in doua reguli de recursiv inainte de teste pentru a vedea daca First este par sau impar. Daca jumatate din numerele sunt chiar si jumatate ciudat, atunci in mod clar de jumatate din apelurile recursive va fi irosita. Cu toate acestea, situatia este de fapt mult mai rau decat faptul ca, din cauza revenire automata Prolog. Backtracking inseamna ca Prolog va incerca in cele din urma toate cele trei reguli de printOrAdd, si doua dintre ele va determina apeluri recursive, fiecare dintre care se va transforma intr-genera doua apeluri recursive, fiecare dintre care... Astfel, pentru o lista de lungime 100, sa zicem, vor exista mai mult de 2 100 de apeluri recursive. Daca Prolog ar putea gestiona un miliard de apeluri recursive pe de alta parte, 2 100 apeluri recursive ar dura cam 2 70 secunde, sau aproximativ 30 bilioane ani.

Solutia, desigur, este de a testa inainte de a face un apel recursiv, asa cum se procedeaza in printOrAdd1 intotdeauna de testare inainte de a face un apel recursiv;. niciodata apel inainte de a testa.

de eroare si mesaje de avertizare
Mesajele de la interpretul Prolog atunci cand programul tau merge bine poate fi dificil pentru un incepator sa interpreteze. Putin se poate spune, in general, ca mesajele variaza de la sistem la sistem. Puteti gasi un ghid pentru unele dintre mesajele de produse SWI Prolog aici. A se vedea, de asemenea, de subliniere variabile, depanare.

fapt
Un fapt este un Prolog clauza cu un cap cu nici un variabile in ea, si nici un organism, cum ar fi

happy(fred).
likes(mary, pizza).

spre deosebire de aceasta regula :

happy(Person) :-
    healthy(Person),
    enough_money(Person), 
    has_friends(Person).

Clauze fara trup cu variabile, cum ar fi...

member(Item, [Item | RestOfList]).

... Se comporta ca niste reguli, in care acestea ofera un mod general de a sti ca, pentru orice Item, ca item este un membru al unei liste din care aceasta este primul element (a se vedea, de asemenea, membru ). Clauza de mai sus este de natura sa genereze un avertisment SWI Prolog ca acest mesaj:

        Singleton variables: [RestOfList]
sa va spun ca variabila RestOfList este mentionata doar o data in codul (deci poate fi o greseala de ortografie, de exemplu). Puteti suprima avertisment, prin scris, in schimb:
member(Item, [Item | _]).
folosind o variabila tacerea: nu-ingrijire, desi acest lucru poate fi mai dificil pentru un om sa urmeze, in special o beginnner la Prolog.

fail
Built-in predicat Prolog fara nici un argument, care, dupa cum sugereaza si numele, nu reuseste intotdeauna. Utile pentru fortarea backtracking si in alte contexte diferite.

A se vedea, de asemenea, true, repeat, schema de intrare.

findall
Built-in predicat findall(+Template, +Goal, -List) este utilizat pentru a colecta o lista List de toate elementele Template care indeplinesc un scop Goal. Exemplu: presupunem

likes(mary, pizza).
likes(marco, pizza).
likes(Human, pizza) :- italian(Human).
italian(marco).
Apoi
?- findall(Person, likes(Person, pizza), Bag).
Person = _G180
List = [mary, marco, marco]

findall reuseste si se leaga List la lista de gol, daca Goal nu are solutii. Acest lucru poate fi convenabil daca nu doriti ca scopul tau de a nu doar din cauza de colectare de solutii este gol. (In alte cazuri, ce-ar vrea scopul de a esua in cazul in care nu exista solutii.)

O alta diferenta intre bagof si findall este gradul de revenire inainte de a face obligatorii al treilea parametru ( List ). De exemplu, sa presupunem:

believes(john, likes(mary, pizza)).
believes(frank, likes(mary, fish)).
believes(john, likes(mary, apples)).

Apoi bagof si findall prezinta urmatorul comportament:

?- bagof(likes(mary, X), believes(_, likes(mary, X)), Bag).
X = _G188
Bag = [likes(mary, fish)] ;

X = _G188
Bag = [likes(mary, pizza), likes(mary, apples)] ;
false.

?- findall(likes(mary, X), believes(_, likes(mary, X)), Bag).
X = _G181
Bag = [likes(mary, pizza), likes(mary, fish), likes(mary, apples)] ;
false.

Puteti vedea ca bagof este colectarea de frank "convingerile lui despre ceea ce mary likes, cu caracter obligatoriu Bag, apoi backtracking si de percepere john "convingerile lui si re-legare a Bag, in timp ce findall gaseste toate credintele fiecaruia si leaga-le pe toate la Bag, doar o singura data.

A se vedea, de asemenea, setof.

fisiere, tell, telling, told, see, seeing, seen, append/1
Atunci cand se scrie un program Prolog, de obicei, faptele si regulile programului sunt stocate intr-un fisier (text), si apoi incarcate in interpretului Prolog. Fisierele au alte utilizari in Prolog, de asemenea.

De exemplu, am putea dori sa scrie un tabel de rezultate, care au fost calculate pentru noi prin programul nostru de Prolog. Se poate utiliza built-in predicate ca write, nl, putc, tab si pe altii sa scrie tabelul, dar in mod implicit acesta va aparea pe ecranul computerului. Pentru a directiona aceasta de iesire la un fisier, vom folosi tell built-in predicat. Sa presupunem ca dorim sa scrie tabelul intr-un fisier numit "mytable.data". De executare obiectivul (pseudo-) tell("mytable.data"), ne spune ca Prolog fluxul de noul curent de iesire trebuie sa fie fisierul "mytable.data". Ulterioare scrie va merge la acest fisier. Cand cineva doreste sa ma opresc din scris la dosar si a relua scris pe ecran, se foloseste predicat built-in told (cu nici un argument). De asemenea, interogarea ?- telling(X). se leaga X la numele fisierului curent de iesire. In cazul in care fluxul de curent de iesire nu este un fisier, atunci X va fi obligat la ceva care indica faptul ca fluxul de curent de iesire este pe ecran - de exemplu, in Unix, X poate fi legat de atom stdout (iesirea standard, care este in mod normal ecranului). Exemplu:

?- tell('mytable.data'), write('***** Table of results *****'), nl, told.
% the file mytable.data should now contain a single line of text as above

Built-in predicat Prolog append/1 este ca si cum tell, cu exceptia faptului ca se ocupa de operatiunile ulterioare a scrie pentru a adauga date la sfarsitul fisierului specificat, decat sa suprascrieti fisierul cu prima operatiune a scrie ulterioare. Daca myothertable.data initial contine, sa zicem, un singur rand, This is the first line, apoi append/1 functioneaza dupa cum urmeaza:

?- append('myotherfile.dat'), write('Here is another line'), nl.
true.
?- halt.
% cat myotherfile.dat # - # is Unix comment char, cat lists file contents
This is the first line
Here is another line
%

Situatia de lectura dintr-un fisier este analog de??a scrie (cu exceptia faptului ca nu exista nici un analog pentru append/1 ). Se poate utiliza built-in predicate cum ar fi read, getc si altii sa citeasca, in mod implicit de la tastatura. De executare obiectivul (pseudo-) see('mydata.text'), ne spune ca Prolog fluxul de intrare curent este nou sa fie fisierul mydata.text. Citeste ulterioare vor veni din acest fisier. Atunci cand se doreste pentru a opri citirea din dosar si a relua citirea de la tastatura, se foloseste predicat built-in seen (cu nici un argument). De asemenea, interogarea ?- seeing(X). se leaga X la numele fisierului de intrare curent. In cazul in care fluxul de intrare curent nu este un fisier, atunci X va fi obligat la ceva care indica faptul ca fluxul de curent de iesire este pe ecran - de exemplu, in Unix, X poate fi legat de atom stdin (intrarea standard, care este in mod normal tastatura). Exemplu:

?- see('mydata.text'), read(X), seen, write(X), nl.
% the first Prolog term in the file mydata.text should now appear
% on the screen, having been read from the file with read(X), and then
% written to the screen with write(X) and nl.

Ce se intampla daca incercati sa cititi dintr-un fisier si nu exista nimic (stanga) pentru a citi, fie din cauza ca fisierul este gol, sau ati citit anterior, tot ce era de citit in acest fisier? In acest caz, Prolog se leaga variabila care a fost argumentul de a read la atom speciale end_of_file. Stiind acest lucru inseamna ca puteti testa dupa o read pentru a va asigura ca nu ati lovit sfarsitul fisierului. Exemplu:

?- see('empty.dat'), read(Term).
Term = end_of_file 

A se vedea, de asemenea, fluxul de intrare curent, fluxul de iesire curent, intrare, iesire. append / 3 nu este legata de append/1.

functor, functor
In Prolog, functorul cuvantul este folosit cu referire la atom la inceputul unei structuri. De exemplu, in likes(mary, pizza), likes este functor. Intr-o structura mai complexa, cum ar fi

persondata(name(smith, john), date(28, feb, 1963))

functorul de nivel superior este numit functor principal - in acest caz persondata - Exista de asemenea un built-in predicat numit functor, folosit pentru a extrage functorul si aritatea a unei structuri.

Exista, de asemenea un built-in predicat functor cu trei argumente: functor(Term, Functor, Arity), care reuseste daca Term este un termen cu functor Functor si aritatea Arity. Exemple:

?- functor(likes(mary, pizza), Functor, Arity).
Functor = likes
Arity = 2 

?- functor(likes(X, Y), Functor, Arity).
X = _G180
Y = _G181
Functor = likes
Arity = 2

?- functor(likes, Functor, Arity).
Functor = likes
Arity = 0 

?- functor(X, likes, 2).
X = likes(_G232, _G233) 

Uneori, exista motive sa doreasca sa aiba functorul undeva, altele decat la inceputul structurii. De exemplu, in expresia X < Y, " < "este un functor:

?- functor(2 < 4, Functor, Arity).
Functor = (<),
Arity = 2.

?- 2 < 4.
true.

?- <(2, 4).
true.
A se vedea op pentru a afla cum functioneaza.

Functor termen este folosit intr-un sens diferit in matematica si in programare functional, si un alt mod din nou in filozofie.

scop
O interogare de interpret Prolog consta din unul sau mai multe goluri. De exemplu, in

?- lectures(john, Subject), studies(Student, Subject).

Exista doua goluri, lectures(john, Subject) si studies(Student, Subject). Un obiectiv este ceva care Prolog incearca sa satisfaca prin gasirea valori ale variabilelor (in acest caz, Student si Subject ), care fac obiectivul reusi. Aceste valoare (e) sunt apoi sa fie legat la variabila (e). Daca Prolog nu este in masura sa faca acest lucru, obiectivul nu reuseste (si Prolog va imprima "false", ca raspuns la interogare). Daca toate obiectivele dintr-o interogare reusi, Prolog imprima legaturile necesare pentru a face interogare de succes. (Daca atunci, in SWI Prolog, tastati un punct si virgula ( ; Prolog) va reiau ideea si sa caute un alt set de legaturi, care vor satisface obiectivele in interogare.

Uneori nu este necesar pentru a lega variabile, in scopul de a satisface un scop. De exemplu, nu exista nici o variabila de a lega, atunci cand scopul este likes(mary, pizza) si baza de date Prolog contine deja likes(mary, pizza). In acest caz, Prolog va imprima "true", ca raspuns la interogare, mai degraba decat legaturi de imprimare.

Gol apar in normele, precum si in interogari. In

happy(Dog) :-
    is_dog(Dog),
    go_for_walk(Dog).
is_dog(Dog) si go_for_walk(Dog) sunt cele doua obiective care formeaza corpul regulii.

halt
Acest "obiectiv", fara nici un argument, va permite sa iesi din Prolog intr-un sistem de operare independent de drum. Tastarea "end-of-file" caractere (control-D, in Unix / Linux) va primi, de asemenea, te va scoate. Diferite sisteme de operare pot utiliza diferite de sfarsit de fisier de caractere. Exemplu de halt :

% prolog
--- Welcome message from Prolog interpreter ---

?- halt.
%

" %" semnele in acest exemplu reprezinta comanda sistem de operare interpret (aka "shell") prompta, nu un Prolog comentariu.

cap
Prima parte a unei Prolog regula. Este separat de corpul de gat simbol :-. Ea are in mod normal, sub forma unui functorului (adica o relatie simbol, urmata de o lista separata prin virgula de parametri, in paranteze. De exemplu, in regula

sister_of(X,Y) :- female(Y), X \== Y, same_parents(X,Y).
sister_of(X,Y) este capul.

daca-then-else, ->
Built-in infix predicat … -> … ; … daca functioneaza ca un... apoi... altceva... instalatiei. Exemplu:

min(A, B, Min) :- A < B -> Min = A ; Min = B.

Aceasta versiune de min (care, la fel ca cel de mai jos, presupune ca A si B sunt numere) spune ca "daca A < B unifica apoi Min cu A unifica altfel Min cu B ". Posibil este mai usor de inteles o versiune cu doua statului de min :

min(A, B, A) :- A <= B.
min(A, B, B) :- B < A.

Aceasta este, de minim A si B este A daca A <= B ; minima este de B daca B < A Cu toate acestea,. -> definitie de min nu ilustreaza functionarea ->.

Codul are o ilustratie mai degraba procedural de programare-simt acesteia, care pot confortul utilizatorilor inceputul anului Prolog. Eventual ar trebui sa fie evitate de catre acestea doar pentru acest motiv! Cel putin, acestea ar trebui sa evite utilizarea acestuia in cazul in care singurul motiv pentru utilizarea acestuia este simti procedurale. Daca utilizarea de -> masiv a redus lungimea codului, astfel ca simplificarea, care ar putea fi un argument pentru utilizarea acestuia.

Semantica detaliata a … -> … ; … este relativ complex. Urmatoarea descriere este citat din textul de ajutor SWI Prolog pe -> :

The ->/2 se angajeaza sa construiasca alegerile facute la cea de partea stanga, distrugerea de alegere puncte creat in interiorul clauza (prin ;/2 ), sau prin goluri chemat de aceasta clauza. Spre deosebire de !/0, alegerea-punctul de predicat ca un intreg (din cauza unor clauze multiple) nu este distrus. Amestec ;/2 si ->/2 actioneaza ca in cazul in care sunt definite prin:
    If -> Then  ; _Else :- If, !, Then.
    If -> _Then ; Else  :-     !, Else.
    If -> Then          :- If, !, Then.
Va rugam sa retineti faptul ca (If -> Then) actioneaza in calitate de (If -> Then ; fail), facand construi esua in cazul in care conditia nu reuseste. Aceasta semantica neobisnuita este parte a ISO si toate standardele de facto Prolog.

Din cauza reducerilor in aceasta definitie, efectul -> si … -> … ; … poate fi neanticipate. Inceput programatorii Prolog ar trebui sa-l foloseasca cu grija la fel de mult ca o taietura. Programatorii care cunosc deja un limbaj de programare cu o daca-then-else construct (cum ar fi C, C + +, Java,...) sunt susceptibile de a reactiona la descoperirea … -> … ; … cu strigate de bucurie si de putin ajutor, si sa-l utilizati la fiecare ocazie. O reactie mai sigur este "daca nu inteleg pe deplin semantica, nu-l folositi."

COMP9414 COMP9814 si studentii de la UNSW le este interzis sa-l foloseasca in orice situatie in care bucati sunt interzise,??in primul rand pentru ca vrem sa va invete cum sa gestioneze fara el (si bucati), in cazul in care este posibil.

indentare
Crestarea codul Prolog intr-un mod standard este o tehnica, impreuna cu comentand aceasta, pentru a face codul mai usor de inteles (de oameni). Modul standard de a stabili o procedura de Prolog este exemplificat mai jos, printr-o procedura pentru a calcula lungimea unei liste. Comentariile au fost omise, pentru a va permite sa se concentreze doar pe indentare.

listlength([], 0).

listlength([Head | Tail], Length) :-
    listlength(Tail, TailLength),
    Length is TailLength + 1.
Regula este sa se alinieze normelor impotriva sefilor de marginea din stanga, si la liniuta clauzele corp, in mod normal, toate cu aceeasi suma. Uneori, este nevoie de mai mult indentarea, de exemplu, in cazul in care codul implica un complex termen, care nu incap pe o singura linie. In acest caz, ar trebui sa liniuta termen sa prezinte structura sa.
    …
    book(
      title('The Strange Case of Dr Jekyll and Mr Hyde and Other Tales of Terror'),
      author(given_names(['Robert', 'Louis']),
             surname('Stevenson')
      ),
      publisher('Penguin Books')
    ), …
    

Uneori, regulile indentarea pot fi indoite: de exemplu, nu este neobisnuit pentru a pune pe o singura linie, de regula cu un corp care contine doar o singura (scurt) clauza.

happy(Person) :- rich(Person).

Comentarii privind Codul indentate ar trebui sa fie, de asemenea, indentate, daca acestea nu pot fi montate pe aceeasi linie ca si cod.

% sum_even_elements(+ListOfNumbers, -Sum): compute Sum of even items in ListOfNumbers
sum_even_elements([], 0). % base case
sum_even_elements([FirstNum | Rest], Sum) :-
    % check whether FirstNum is even
      0 is FirstNum mod 2,
    % if we get here it was even, so process rest of list and add FirstNum to result
      sum_even_elements(Rest, SumForRest),
      Sum is FirstNum + SumForRest.
sum_even_elements([FirstNum | Rest], Sum) :-
    % this rule handles the case where FirstNum is /not/ even
      0 =\= FirstNum mod 2,
      sum_even_elements(Rest, Sum).
Acest exemplu este mai comentat foarte intens decat este necesar, pentru a demonstra conventie comentare.

A se vedea, de asemenea, comentariile si spatiu alb.

infix si predicatele prefix / proceduri
Cele mai multe incorporat in constructii in Prolog, si, in mod implicit, procedurile si termenii care va scrie, utilizeaza sintaxa prefix - care este, numele termen lung / procedura ( functor ) precede argumentele (care sunt inconjurate de paranteze si separate prin virgule). De exemplu, atunci cand vom folosi built-in predicat member, ne scrie ceva de genul member(Item, [a, b, c]) - in primul rand numele predicatului, member, apoi "(", atunci primul argument, Item, apoi o virgula, apoi al doilea argument, [a, b, c], apoi ")".

Cu toate acestea, cu built-in predicate precum =, < si >, care sunt, de obicei, scrise intre argumentele lor, la fel ca in First < Max, vom scrie, in Prolog ca in matematica, in notatie infix. Un alt infix built-in "predicat" este is, care este folosit in evaluarea expresiilor aritmetice.

Este posibil in Prolog pentru a defini infix ta (si postfix) operatori, si sa modifice manipularea sintactica a operatorilor prefix - a se vedea op.

de intrare in Prolog, read, end_of_file, get, get_byte, getc, flush_output
Intrare in Prolog nu este intotdeauna necesar, ori de cate ori interogarea procesului ofera toate de intrare care este nevoie. Daca este necesara introducerea explicita, un set de extra-logice predicate built-in este disponibil. Acestea includ:

  • read(X), care prevede urmatoarele termen in fluxul de intrare curent, ceea ce inseamna ca fereastra de pe statia de lucru dvs. daca nu ati facut ceva usor fantezie cu fisiere, si unifica cu variabila X.

  • end_of_file : daca nu exista nimic pentru a citi in fluxul de intrare curent, read(X) determina X sa fie legat de simbolul special end_of_file. Daca nu esti absolut sigur ca aveti un alt mod de a sti cand nu se vor mai multe date de intrare pentru a citi, ar trebui sa verificati pentru a va asigura ca termenul pe care le-ati citit, nu este end_of_file. Modalitati ca ati putea fi (aproape) absolut sigur: citeste primul termen ar putea fi un numar care indica cate termeni suplimentare care urmeaza sa fie citite.

  • get_byte(C), care citeste un singur caracter din fluxul de intrare curent, si se leaga cod echivalent intreg, in intervalul 0 la 255. Daca nu exista un caracter pentru a citi mai departe, C este obligata sa –1.

  • get(C) este ca get_byte(C), cu exceptia faptului ca citeste primul non-gol caracter, daca este cazul, din fluxul de intrare curent.

  • flush_output este de fapt un scop de iesire, ceea ce garanteaza faptul ca nici o iesire pe care a fost solicitat, dar nu este inca realizat, se face chiar acum. De iesire nu s-ar putea fi finalizata pana cand nu este suficient pentru a face merita, sau pana cand o operatiune ca flush_output fortelor ea.

Exemplul 1: Sa presupunem ca vine de intrare este de la fereastra statia de lucru a utilizatorului si de faptul ca procedura de read_a_char este definita ca:

read_a_char(C) :-
   write('Type: '), flush_output,
   get_byte(C).

Apoi, aveti posibilitatea sa efectuati urmatoarele - act de faptul ca 43 este codul caracterului pentru caracterul +.

?- read_a_char(Ch).
Type: +
Ch = 43

A se vedea, de asemenea, atom_codes, de transformare a unui sir de coduri de caractere numerice la un atom format din caractere reprezentate de aceste coduri de caractere. De exemplu, 102, 105, 100, si 111 sunt codurile numerice pentru literele f, i, d, si o. atom_codes poate fi utilizat dupa cum urmeaza:

?- atom_codes(A, [102, 105, 100, 111]).
A = fido

Exemplul 2: Sa presupunem ca exista un fisier numit inputdata, care contine pe prima sa linie pe termen
likes(mary, pizza).
cu o oprire completa de la sfarsitul termenului.

?- see('inputdata'), read(Term), seen.
Term = likes(mary, pizza)

NB: Nu oprire completa de la sfarsitul lui Termen obligatoriu.

schema de intrare
In orice limbaj de programare, este posibil sa se specifice schemelor ca modul de cod de activitati comune de programare. Ceea ce urmeaza este o schema pentru a citi materialul dintr-un fisier si de prelucrare se

dountilstop :-
  repeat,
  read(X),
  (X = stop, !
   ;
   process(X),
   fail
  ).

In acest caz, codul citeste datele, un termen la un moment dat, din fluxul de intrare curent. Pentru a face ca fluxul de intrare un fisier numit, sa zicem, inputdata, v-ar invoca cod, dupa cum urmeaza:

?- see('inputdata'), dountilstop, seen.

Apelul de a fail este acolo pentru a forta backtracking. Apelul de a repeat este acolo pentru a forta codul pentru a repeta la nesfarsit - care este, pana cand ceva incheie backtracking. Acest "ceva" este taiat dupa X = stop - in cazul in care termenul este citit atom stop, obiectivul X = stop reuseste, taiate este executat, si a statului se termina.

Pentru a utiliza schema, inlocuiti operatiunea citesc cu cel dorit (ar putea fi getc sau ratom sau...), se inlocuieste apelul la process cu un apel la o procedura care face tot ce doriti sa faceti la datele, si tu esti in afaceri. De fapt - veti gasi, probabil, alte cateva ajustari sunt necesare, dar cel putin esti pe drumul cel bun.

A se vedea, de asemenea, read, repeat, see, seen, ; (sau), si fail.

is, de evaluare
is incorporat in predicat este folosit in Prolog pentru a forta de evaluare a expresiilor aritmetice. Daca scriu doar ceva de genul X = 2 + 4, rezultatul este de a lega X la termenul unevaluated 2 + 4, nu 6. Exemplu:
     ?- X = 2 + 4.
     X = 2+4

Daca in loc sa scrii X is 2 + 4, Prolog organizeaza pentru al doilea argument, media aritmetica expresia 2 + 4, care urmeaza sa fie evaluat (da rezultat 6 ) inainte de legare rezultatul la X.

     ?- X is 2 + 4.

     X = 6

Este numai si intotdeauna al doilea argument, care este evaluat. Acest lucru poate duce la unele biti ciudate cu aspect de cod, de catre standardele matematice. De exemplu, mod este operatorul de restul dupa--diviziune, astfel incat in Prolog, pentru a testa daca un numar N este chiar, vom scrie 0 is N mod 2, mai degraba decat de obicei matematic prin care se dispune: N mod 2 = 0.

Care este diferenta intre N = 1 si N is 1? Intr-adevar final, nimic. Cu toate acestea, cu N is 1, Prolog se cere sa faca un pas suplimentar pentru a lucra in valoare de 1 (care, deloc surprinzator, este 1). Se poate argumenta ca, este mai bine sa utilizati N = 1, deoarece acest lucru nu necesita o evaluare inutile.

Mesajul este: utilizarea is numai atunci cand aveti nevoie pentru a evalua o expresie aritmetica.

De fapt, nu aveti nevoie sa utilizati is de a evalua expresii aritmetice, care sunt argumentele pentru aritmetica operatorii de comparatie >,> =, <= <, =: = (egal), si = \ = (nu este egal), toate din care evalueze in mod automat argumentele lor.

Nota sintaxa is : fie
<Variabila> is <expresie>
sau
<Numerica constanta> is <expresie>
Astfel, lucruri cum ar fi X*Y is Z*W nu functioneaza, astfel cum a X/Y este o expresie, nu o variabila - utilizeaza fie

0 is X*Y - Z*W
sau
X*Y =:= Z*W
in schimb.

O greseala des intalnita, pentru oamenii obisnuiau sa limbaje de programare procedurale cum ar fi C si Java, este de a incerca sa schimbe legarea unei variabile, folosind un obiectiv cum ar fi N is N + 1. Acest obiectiv nu va reusi niciodata, deoarece necesita N pentru a avea aceeasi valoare ca si N + 1, ceea ce este imposibil. Daca va aflati dorinta de a face ceva de genul asta, te puteai uita la codul de factorial pentru inspiratie.

O alta greseala comuna este de a incerca un obiectiv care implica is inainte de variabila (e) de pe partea dreapta a is a / au fost instantiat. Prolog nu poate evalua o expresie aritmetica, in cazul in care nu cunoaste valorile variabilelor in expresie. Acesta este motivul pentru care nu reuseste urmatorul exemplu:

?- X is Y + 1, Y = 3.
ERROR: is/2: Arguments are not sufficiently instantiated
Comparati acest lucru cu:
?- Y = 3, X is Y + 1.
Y = 3,
X = 4.

liste de
O lista in Prolog este scris ca o secventa separata prin virgula de elemente, intre paranteze drepte. De exemplu, [1, 2, 3] este o lista.

Lista gol este scris [].

O lista cu doar un singur element, spune numarul 7, este scris [7].

Frecvent, este convenabil sa se faca referire la o lista prin acordarea primul element, si o lista constand din restul elementelor. In acest caz, o lista scrie ca [First | Rest].

Am exprimat acest lucru aici folosind variabile, dar acest lucru nu trebuie sa fie asa, de exemplu, am putea scrie [1, 2, 3] astfel cum:

  • [1 | [2, 3]]
  • [1 | Rest], in cazul in care Rest este obligata sa [2, 3]
  • [First | [2, 3]], in cazul in care First este obligata sa 1
  • [First | Rest], in cazul in care First este legat de 1, si Rest este obligata sa [2, 3]
  • [1, 2 | [3]]
  • [1, 2, 3 | []]
si mult mai multe posibilitati.

Ar trebui sa scrie intotdeauna lista ta Prolog, in formatul cel mai compact rezonabil. Deci, spre exemplu, in timp ce [X | []] este aceeasi lista ca [X], a doua versiune este mult mai usor de citit, de aceea trebuie sa-l utilizati.

Listele pot fi, de asemenea, exprimata printr-o sintaxa termen normale, folosind numele de built-in predicat . - care este, o oprire completa sau perioada. In acest caz, atomul de lista goala ( [] ) trebuie sa fie folosita pentru a termina lista. Cu toate acestea, aceasta abordare este mai greoaie, si in practica, oamenii folosesc [1, 2, 3] - sintaxa stil. Exemplu:

?- X = .(1, .(2, .(3, []))).
X = [1, 2, 3]

listing
Built-in meta-predicat lista poate fi utilizat pentru a verifica ceea ce este de fapt in baza de date Prolog in timpul unei sesiuni de Prolog. Ea vine in doua arome: cu nici un argument ( listing/0 ), si cu un singur argument ( listing/1 ). Fara argumente, provoaca continutul bazei de date Prolog pentru a fi imprimate. Cu un singur argument - numele unei proceduri - afiseaza doar normele si / sau faptele cu privire la aceasta procedura. Exemple, presupunand ca ati inceput Prolog cu un fisier de program care contine faptele si normele
happy(ann). happy(tom). happy(X) :- rich(X). rich(fred).

?- listing.
happy(ann).
happy(tom).
happy(A) :-
        rich(A).

rich(fred).
true.
?- listing(happy).
happy(ann).
happy(tom).
happy(A) :-
        rich(A).
true.

In cazul de listing/0, Prolog poate imprima, de asemenea, unele interne de casa-pastrare a informatiilor.

member built-in predicat
Acest predicat are un element si o lista de argumente, si reuseste in cazul in care elementul este un membru al listei:

?- member(a, [b, a, c]).
true.

?- member(X, [b, a, c]).
X = b ;
X = a ;
X = c ;

false.
?- member(happy(fido), [angry(rex), happy(fido)]).
true.

?- member(a, [b, [a], c]).
false.

?- member([a], [b, [a], c]).
true.

?- member(a, Y).
Y = [a|_G310] ;
Y = [_G309, a|_G313] ;
Y = [_G309, _G312, a|_G316] ;
Y = [_G309, _G312, _G315, a|_G319] ;
... Si asa mai departe atata timp cat apasati " ; ". Raspunsul la aceasta interogare ultima spune ca a este un membru al unei liste (uninstantiated), Y, daca a membru este primul sau al doilea membru al sau sau al treilea membru al patrulea membru sau...
Variabilele _G309, _G310, _G313, etc reprezinta biti a listei Y pe care le-am nici o informatie despre.

A se vedea, de asemenea, backtracking.

memoisation
Memoisation inseamna stocarea un fapt (de exemplu, folosind asserta ), care a fost dedus in timpul executiei programului, in baza de date Prolog, pentru a evita, eventual, sa se deduca avand in acelasi fapt din nou, mai tarziu, in executarea programului.

Daca acest lucru este in valoare de a face depinde de natura problemei. Daca faptele sunt in mod regulat re-deduce (eventual, ca o consecinta a unei solutii recursive), apoi memoisation ar putea fi o idee foarte buna. Unii algoritmi efectua recursivitate duble sau multiple (care este, ei "recurse" pe mai mult de o variabila), si ambele ramuri recursive pot ajunge re-calcularea acelasi lucru, ceea ce conduce, in unele cazuri, la cresterea exponentiala a numarului de cazuri sub- ca dimensiunea problemei creste. Exemplul clasic este calculul recursiv al n-lea numar Fibonacci, care este (recursiv) * definite prin:

f 0 = f 1 = 1, si,
pentru n> 1, f n = f n -2 + f n -1.

* Retineti ca o expresie non-recursive pentru f n este, de asemenea, cunoscut - ceva ce noi ignoram aici, deoarece acest exemplu este de aproximativ recursivitate.

desen de copac apel recursiv pentru numarul Fibonacci f_6

Dupa cum poate fi vazut (sau, mai degraba, extrapolat) din diagrama, numarul de apeluri creste exponential, precum si numerele lui Fibonacci devenit rapid imposibil de a calcula de catre programul recursiv naiv:

fib_naive(N, Result) :-
    N > 1,
    Nminus2 is N - 2,
    Nminus1 is N - 1,
    fib_naive(Nminus1, FibNminus2),
    fib_naive(Nminus1, FibNminus1),
    Result is FibNminus1 + FibNminus2.
Cu toate acestea, de memoising, modul de calcul devine perfect fezabil pentru valori mult mai mari ale lui n:
fib_memo(0, 1).
fib_memo(1, 1).
fib_memo(N, Result) :-
        N > 1,
        Nminus2 is N - 2,
        Nminus1 is N - 1,
        fib_memo(Nminus2, Fib2Nminus2),
        fib_memo(Nminus1, Fib2Nminus1),
        Result is Fib2Nminus1 +  Fib2Nminus2,
        asserta((fib_memo(N, Result) :- !)).

Nota folosirea asserta pentru a stoca valoarea memoised la inceputul colectie de fapte pentru fib_memo, astfel incat acesta vor fi verificate inainte de a incerca regula. Retineti, de asemenea taiate ( ! ) la sfarsitul assserta regula-ED, care se opreste algoritmul de backtracking si incercarea de a statului, dupa ce a gasit o solutie folosind valoarea memoised (e). Aceasta bucata de carne este necesar, in caz contrar, in timp ce prima solutie ar fi gasit rapid, codul ar gasi in mod repetat aceeasi solutie un numar foarte mare de ori, de a lua o cantitate imensa de timp de calcul.

A se vedea, de asemenea, afirma, dinamic.

More?
Raspunsul de obicei la o interogare Prolog care nu are variabile in el, sau care are doar subliniaza in ea este true. sau false.. Cu toate acestea, in unele versiuni ale Prolog, inclusiv versiunile recente ale SWI-Prolog (de exemplu, versiunea 5.6.47), un alt posibil raspuns poate avea loc: More?. Acest lucru inseamna (1) true. si (2) faptul ca exista alte alternative pentru a explora Prolog, care ar putea permite sa ajunga la concluzia true. intr-un mod diferit. Prolog Adica poate fi in masura sa dovedeasca faptul ca interogare este adevarat in mai mult de un fel. De exemplu, sa presupunem ca likes(jane, pizza) se afla in program Prolog ca un fapt, dar poate fi, de asemenea, deduce folosind o regula si cateva alte fapte.

?- likes(jane, pizza).
More? 

More? este o solicitare pentru a va permite pentru a afla daca acest lucru este asa - si anume ca interogarea poate fi dovedita in mai mult de un fel. Tastati o virgula daca doriti Prolog sa mergeti mai departe si sa caute o dovada diferite. Tipul de intoarcere daca sunteti multumiti cu o singura dovada.

Daca doriti pentru a suprima acest comportament, aveti posibilitatea sa inserati reduceri pentru a preveni backtracking ca este gasirea suplimentar (posibil) dovezi, sau puteti, in SWI-Prolog, utilizeaza aceasta interogare:
set_prolog_flag(prompt_alternatives_on, groundness).
sau, alternativ, a pus urmatoarea directiva in codul sursa Prolog:
:- set_prolog_flag(prompt_alternatives_on, groundness).

Ati putea fi, de asemenea, posibilitatea de a evita raspunsurile de More?, in unele cazuri, prin re-comanda relevante clauze in programul tau.

Iata cateva codul de exemplu pentru a demonstra More? :

happy(fido).
happy(rex).
happy(Dog) :- is_dog(Dog), walkies(Dog).
happy(Dog) :- is_dog(Dog), chase_car(Dog).
is_dog(fido).
is_dog(rex).
walkies(fido).
walkies(rex).
chase_car(fido).
Exista trei moduri de a dovedi fido este happy : de fapt, si de la fiecare dintre cele doua reguli. Deci:
Prolog Dialogul Comentariu
?- happy(fido).
More? ;
More? ;
true.

?- happy(rex).
More ;
More ;
false.
happy(fido) proven using fact
happy(fido) proven using "walkies" rule
happy(fido) proven using "chase_car" rule


happy(rex) proven using fact
happy(rex) proven using "walkies" rule
happy(rex) not provable using "chase_car" rule

reciproca recursivitate
Uneori, o procedura nu se refera in mod explicit la sine (acest lucru ar fi (simplu) recursivitate ), ci mai degraba se refera la o procedura de secunde, care la randul sau, se refera la prima. Aceasta stabileste un recursivitate in doua etape reciproc. Trei sau mai multe etape situatiile reciproca recursivitate pot aparea, de asemenea. Conditiile obisnuite aplicabile recursiei trebuie sa aiba loc - trebuie sa existe o "sucursala banale" undeva in ciclul de procedurile recursive reciproc, si undeva in ciclul de ceva trebuie sa se intample pentru a se asigura ca, de fiecare data in jurul ciclului, o versiune mai simpla a problemei este in curs de solutionare.

gat
Simbol :-, utilizat intr-un Prolog regula pentru a separa capul de corp. De obicei, ca si cum ar citi. Astfel

a :- b, c.

este citit ca

a (este adevarat) in cazul in care b si c (sunt adevarate).

negatie, nu,, \+
Conceptul de negatiei logice in Prolog este problematica, in sensul ca singura metoda pe care Prolog se poate folosi pentru a spune daca o propozitie este falsa este de a incerca sa dovedim acest lucru (de la fapte si normele pe care le-a fost spus despre), si apoi daca aceasta incercare esueaza, se ajunge la concluzia ca propozitia este falsa. Acest lucru este mentionat ca negatia ca esec. O problema evidenta este ca Prolog ar putea sa nu fi fost spus unele fapt critice sau regula, astfel incat acesta nu va fi in masura sa dovedeasca propunerea. Intr-un astfel de caz, falsitatea propozitia este doar relativ la "mini-lume-model" definit de faptele si normele cunoscute de catre interpret Prolog. Acest lucru este uneori mentionata ca ipoteza inchis lume.

O problema mai putin evident este faptul ca, in functie din nou pe normele si faptele cunoscute de catre interpret Prolog, aceasta poate dura foarte mult timp pentru a stabili faptul ca propunerea nu pot fi dovedite. In anumite cazuri, aceasta s-ar putea "lua" de timp infinit.

Din cauza problemelor de negatiei-ca-esec, negatia in Prolog este reprezentat in Prolog interpreti moderne folosind simbolul \+, care se presupune a fi un mnemonic pentru a nu demonstrabile cu \ in picioare pentru ca nu si + pentru demonstrabile. In practica, interpreti Prolog actuale tind sa sustina mai mari operatorul not, precum si, asa cum el este prezent in o multime de cod Prolog mai vechi, care s-ar rupe daca not nu au fost disponibile.

Exemple:

?- \+ (2 = 4).

true.

?- not(2 = 4).

true.

Operatorii de comparatie Aritmetica in Prolog sunt dotate fiecare cu o negatie, care nu are un "negatia ca esec" problema, pentru ca este intotdeauna posibil sa se determine, de exemplu, daca doua numere sunt egale, desi pot exista probleme de aproximare in cazul in care comparatia este intre numere fractionare (in virgula mobila). Deci, este, probabil, cel mai bun de a utiliza aritmetica operatorii de comparatie in cazul in care cantitatile numerice sunt comparate. Astfel, o modalitate mai buna de a face comparatiile de mai sus ar fi:

?- 2 =\= 4.

true.

numar, number(–)
Numerele in Prolog pot fi numere intregi, cum ar fi:
1 1313 0 -97 9311

sau numere fractionare, cum ar fi:
3.14 -0.0035 100.2
Gama de numere care pot fi utilizate este probabil sa fie dependenta de numarul de biti (cantitatea de memorie de calculator), utilizat pentru a reprezenta numarul. Tratamentul de numere reale in Prolog poate varia de la punerea in aplicare la punerea in aplicare - numere reale, nu sunt toate ca in mare masura utilizate in programele Prolog, ca accentul in Prolog este pe manipulare simbol.

number este, de asemenea, numele unui predicat built-in care testele de argumentul sau unic si reuseste, daca acest argument este un numar de exemple.:

?- number(2.1).
true.
?- number(-8).
true.
?- X = 7, number(X).
X = 7.
?- number(1+1).
false.
Ultima interogare nu reuseste pentru ca 1 +1 este o expresie unevaluated nu, un numar. A se vedea este, pentru mai mult pe evaluare.

once
Built-in Prolog extra-logic predicat once are un singur argument, care trebuie sa fie un "termen apelabile" - unul care are sens ca un scop - de exemplu, happy(X) are sens ca un scop, dar 23 nu - si invita la termen in asa fel incat sa produce doar o solutie. Acesta este definit ca:

once(P) :- P, !.

A se vedea, de asemenea !, call, backtracking.

op, infix, prefix, si operatori postfix, intaietate in Prolog
Sintaxa:

:- op(+Precedence, +Type, :Name).

Prolog built-in predicat op serveste pentru a defini tipul si Precedenta de infix si postfix, si operatorii prefixul in termeni Prolog. Termeni Prolog incepe in mod normal, cu functor (de exemplu, likes, in likes(mary, pizza) ), dar exista exceptii - de exemplu, expresii aritmetice sunt scrise in mod obisnuit infix (de exemplu ca X + 1, mai degraba decat +(X, 1) ), si negatia pot fi scrise fara paranteze, ca un operator prefix: not P.

Tabelul de mai jos listeaza operatorii predefinite infix in SWI-Prolog. Poate veti dori sa adaugati operatori infix de dumneavoastra. De exemplu, ati putea dori sa definiti o infix and. Aceasta se poate face dupa cum urmeaza:

:- op(700, xfy, and).

Aceasta declara and sa fie un operator cu prioritate 700 si de tip xfy.

Nota doua lucruri: (1) faptul ca aceste lucruri sunt prevazute doua ca operatori nu inseamna ca o operatiune este efectuata atunci cand sunt intalnite. Acest lucru nu este de obicei cazul; si??(2) declaratia de un operator afecteaza doar aspectul exterior al operatorului in program - pe plan intern, reprezentarea standard este utilizat - de exemplu, X + 1 este intr-adevar intern reprezentat de Prolog ca +(X, 1).

Precedence este un numar intreg intre 0 si 1200. Precedence 0 elimina declaratia. Type este unul din: xf, yf, xfx, xfy, yfx, yfy, fy sau fx. f indica pozitia functorului, in timp ce x si y indica pozitia a argumentelor. Astfel xfx, xfy, si yfx indica toate un operator infix. y ar trebui sa fie interpretat in sensul ca "in aceasta pozitie cu un termen egal cu sau mai mica decat precedenta a functorului prioritate ar trebui sa apara". Pentru x prioritate a argumentului trebuie sa fie strict mai mica decat cea a functorului. Prioritatea unui termen este 0, cu exceptia cazului in functor principal este un operator, caz in care prioritate este ordinea de prioritate a acestui operator. Un termen intre paranteze (...) are prioritate 0.

Pentru a vedea cum functioneaza, ia in considerare expresia aritmetica a - b - c. In matematica normale, acest lucru este interpretat ca (a - b) - c, mai degraba decat a - (b - c). Pentru a realiza acest lucru, operatorul infix binar - trebuie sa fie declarate ca fiind de tip yfx, astfel incat primul argument are prioritate fata de al doilea. Apoi, pe plan intern, a - b - c va fi reprezentat ca -(-(a, b), c), mai degraba decat -(a, -(b, c)).

Built-in Operatorii (SWI-Prolog)

PREC. Tip Operator
1200 XFX ->,: -
1200 fx : -?, -
1150 fx dinamic, discontiguous, initializarea, module_transparent, multifisier, thread_local, volatile
1100 xfy ;, |
1050 xfy ->, Op *->
1000 xfy ,
954 xfy \
900 FY \ +
900 fx ~
700 XFX <, =, =.., = @ =, =: =, = <, ==, = \ =,>,> =, @ <, @ = <, @>, @> =, \ =, \ = =, este
600 xfy :
500 yfx +, -, / \, \ /, XOR
500 fx +, -,, \?
400 yfx *, /, / /, Rdiv, <<,>>, mod, rem
200 XFX **
200 xfy ^

Retineti ca toti operatorii pot fi redefinite de utilizator, cel mai frecvent accidental si cu rezultate dezastruoase.

sau, logice disjunctie, ;
Jonctiune con logic (logic-si,?) de goluri este realizat in Prolog prin separarea obiective prin virgule:

happy(X) :- rich(X), famous(X).

spune ca X este happy daca X este bogata si X este faimos. Ce zici de-logic sau,?, de asemenea, numit jonctiune DIS? Daca vrem sa spunem ca X este happy daca X este rich sau daca X este famous, avem doua posibilitati:

  1. folosesc doua reguli alternative
  2. utilizeaza ; operatorul (pronuntat "sau").

Optiunea 1:

happy1(X) :- rich(X).
happy1(X) :- famous(X).

Optiunea 2:

happy2(X) :- rich(X) ; famous(X).

Uneori este necesar, sau cel putin recomandabil, pentru a incheia paranteze ( ) in jurul valorii de o disjunctie pentru a face clar ceea ce modul in care conjunctii si disjunctii interactioneaza. Daca lasati afara paranteze, Prolog are propriile reguli cu privire la precedenta a-si logice si logico-sau, care ar putea sau nu s-ar putea corespunde cu ceea ce intentionati. Daca utilizati paranteze, lucrurile din interiorul parantezelor se fac in primul rand, asa ca totul este extrem de clara.

Optiunea 3:

happy3(X) :- attractive(X), ( rich(X) ; famous(X) ).

Aceasta spune ca X este happy3 daca X este atractiv, iar X este fie bogat sau faimos:
happy3 (X)? atractive (X)? (bogat (X)? celebre (X)).*

* Dictionar Prolog doreste sa recunoasca faptul ca o serie de religiile lumii si filozofii nu ar fi de acord ca a criteriilor specificate pentru happy1, happy2, si happy3 sunt fie necesara, nici suficienta pentru fericire. Definitiile mentionate in prezentul articol, sunt, prin urmare, pur doreste a fi exemple de programare Prolog, si nu ar trebui sa fie luata ca un ghid practic pentru viata. Multumesc.

iesire in Prolog
Iesire in Prolog nu este intotdeauna necesar, ori de cate ori este variabila legaturile intoarcere toate informatiile necesare. Daca iesire explicita este necesara, un set de extra-logice predicate built-in este disponibil.
Acestea includ:

  • write(X), care scrie termenul X la fluxul curent de iesire (ceea ce inseamna fereastra pe statia de lucru dvs. daca nu ati facut ceva fancy ).
  • print(X, …) care scrie un numar variabil de argumente pentru a fluxului de curent de iesire. Daca un argument este un sir de caractere (cum ar fi 'Hello world!\n' ), atunci sirul este tiparita fara ghilimele, precum si orice '\n' si '\t' sunt interpretate ca si linie noua fila, respectiv. Un rand nou liber este tiparita la sfarsitul operatiei de imprimare.
  • prin(X, …) este ca print cu exceptia faptului ca nu adaugati o linie noua la sfarsitul productiei.
  • tab(N) imprima N spatii pentru productie - N ar trebui sa fie un numar.
  • nl incepe o linie noua.
  • put(C) imprima un caracter unic pentru fluxul curent de iesire. C ar putea fi legat la un numar din intervalul 0 - 255, caz in care numarul este tratata ca un cod de caracter, iar caracterul echivalent este tiparita, sau ar putea fi legat la un personaj, de exemplu, C = 'a', in care caz evident caracterul este imprimat.

predicat
Folosit pentru a desemna functionalitatea oferita de un Prolog procedura. In acest dictionar, avem tendinta de a vorbi despre procedurile in cazul in care codul este scris de programator, dar predicate atunci cand functionalitatea este built-in, ca si in cazul membru.

procedura
O procedura in Prolog este un grup de clauze cu privire la aceeasi relatie, de exemplu:

is_a_parent(Parent) :- father_of(Parent, _Child).
is_a_parent(Parent) :- mother_of(Parent, _Child).

Aici, doua clauze, impreuna, definesc o conditie pentru ca cineva sa fie o societate-mama - impreuna ele formeaza o procedura.

A se vedea, de asemenea, subliniaza, pe motiv pentru a pune o linie de subliniere ( _ ), caracterul in fata variabilei _Child.

interogare
O interogare este o lista de una sau mai multe goluri pentru a tastate de interpret Prolog ?- prompt, separate prin virgule, si terminat cu un punct ( . ). De exemplu,
?- lectures(john, Subject), studies(Student, Subject).
este o interogare care cuprinde doua goluri. Prolog incearca sa satisfaca obiectivele, iar in cazul in care reuseste sa faca acest lucru, interogarea se spune ca reusi. Daca nu, interogarea esueaza.

In cazul in care interogarea nu reuseste, tipuri de Prolog " false. ". Daca reuseste, Prolog fie tipuri lista de variabile legaturi a trebuit sa-si asume, in scopul de a face interogarea de succes, sau, in cazul in care nu s-au legaturi variabila este necesar, tipuri de " true. ".

Daca mai multe legaturi variabila permite interogarea pentru a reusi, atunci in mod normal (de exemplu, in absenta de bucati ) toate legaturile vor fi dactilografiate afara, unul dupa altul, cu ghidul de Prolog tastand o ; pentru a permite sistemului Prolog stiu ca sunt gata pentru a vedea urmatorul set de legaturi.

recursivitate
O recursiv regula este aceea care se refera la el insusi. Asta este, ei corp include un obiectiv care este o instanta a relatiei care apare in capul statului. Un exemplu bine cunoscut este member procedura :
member(Item, [Item|Rest]).
member(Item, [_|Rest]) :- member(Item, Rest).
Cea de a doua clauza este in mod clar recursiv - member are loc atat in cap si corp. O procedura recursiv poate lucra din cauza a doua lucruri:
  1. instanta a relatiei (ca member ) in organism este intr-un mod mai simplu decat ca, in cap, astfel incat Prolog se cere sa rezolve o problema simpla. (In member, lista care este argumentul pentru member in organism este mai mica decat cea de unul in cap.)
  2. trebuie sa existe o "banala sucursala", "caz de baza" sau "caz limita" pentru a recursivitate - care este, o clauza care nu implica recursivitate. (In cazul de member, prima clauza este ramura de banal - se spune ca member reuseste daca Item este primul membru al listei care este al doilea argument.)

O structura de date recursiva este una in care structurile includ substructurile al carei principiu functor este aceeasi cu cea a intregii structuri. De exemplu, structura arborescenta:
tree(tree(empty, fred, empty), john, tree(empty, mary, empty))
este recursiva. Structuri de date recursive necesita proceduri recursive pentru a le procesa.

Aceasta poate ajuta, in intelegerea recursivitate, pentru a separa diferite adancimi de invocare recursiva a normelor Prolog, prin elaborarea Dulapuri in jurul valorii de partile care corespund la o invocatie particular, oferindu-si separate (dar sistematice) nume variabile in fiecare invocare. Deci, daca regula implica o variabila X, apoi, in invocare in primul rand, ne referim la X ca X1, in timp ce in al doilea (recursiv) invocare, ne referim la noul X ca X2, si asa mai departe.

Sa incercam acest lucru cu procedura de recursiv sumlist. In fiecare apel recursiv de sumlist, exista o instanta separata a variabilelor First, Rest, Sum, si SumOfRest, iar acestea se disting prin indici - asa First 1 este instanta de First in apelul de nivel superior de sumlist, si First 2 este instanta de First in apelul recursiv prima sumlist.

% sumlist(NumList, SumOfList) - binds SumOfList to the sum
% of the list NumList of numbers.
% Rule 1:
sumlist([], 0).
% Rule 2:
sumlist([First | Rest], Sum) :-
   sumlist(Rest, SumOfRest), % Goal 2.1
   Sum is First + SumOfRest. % Goal 2.2
si interogarea
?- sumlist([5, 2, 1], Answer).

sumlist[5, 2, 1], Answer).
Alege Articolul: doar 2 meciuri regula, cu
First 1 = 5; Rest 1 = [2, 1]; Sum 1 = Answer
Obiectivul 2.1: sumlist(Rest 1, SumOfRest 1 ),
sumlist([2, 1], SumOfRest 1 ),
Alege Articolul: doar 2 meciuri regula, cu
First 2 = 2; Rest 2 = [1]; Sum 2 = SumOfRest 1
Obiectivul 2.1: sumlist(Rest 2, SumOfRest 2 ),
sumlist([1], SumOfRest 2 ),
Alege Articolul: doar 2 meciuri regula, cu
First 3 = 1; Rest 3 = []; Sum 3 = SumOfRest 2
Obiectivul 2.1: sumlist(Rest 3, SumOfRest 3 ),
sumlist([], SumOfRest 3 ),
Alege Articolul: regula doar 1 meciuri, cu
0 = SumOfRest 3
? SumOfRest 3 = 0
Obiectivul 2.2: Sum 3 is First 3 + SumOfRest 3.
= 1 + 0
= 1
? SumOfRest 2 = Sum 3 = 1
Sum 3 is First 3 + SumOfRest 3.
= 1 + 0
= 1
? SumOfRest 2 = Sum 3 = 1
Obiectivul 2.2: Sum 2 is First 2 + SumOfRest 2.
= 2 + 1
= 3
? SumOfRest 1 = Sum 2 = 3
Sum 2 is First 2 + SumOfRest 2.
= 2 + 1
= 3
? SumOfRest 1 = Sum 2 = 3
Obiectivul 2.2: Sum 1 is First 1 + SumOfRest 1.
= 5 + 3
= 8
? Answer = Sum 1 = 8
Sum 1 is First 1 + SumOfRest 1.
= 5 + 3
= 8
? Answer = Sum 1 = 8

Incearca sa faci un Prolog urma de aceeasi interogare si de procedura, si comparati rezultatele.

Iata cateva sfaturi pentru scris, procedurile recursive in Prolog..

A se vedea, de asemenea, recursia reciproca.

relatie
Ceea ce priveste cuvantul, in Prolog, dispune de o intelesul obisnuit matematic. A se vedea relatiile si functiile daca nu sunteti sigur despre ceea ce este. O relatie unar este un set de obiecte de partajare toate unele de proprietate. Exemplu:

is_dog(fido).
is_dog(rex).
is_dog(rover).

O relatie binara este un set de perechi de toate de care sunt legate in acelasi mod. Exemplu:

eats(fido, biscuits).
eats(rex, chocolate).
eats(rover, cheese).
eats(lassie, bone).

In mod similar pentru relatii ternare (triple) si asa mai departe. In exemplele de mai sus, is_dog si eats sunt functorilor pentru relatiile. Prolog stocheaza informatii in forma de relatii, sau mai precis instante relationale, cum ar fi cele de mai sus, si, de asemenea, sub forma de norme.

De asemenea, este posibil in Prolog de??a avea relatii nullary (o relatie cu nici un argument), desi acestea nu sunt, probabil, de multe ori folosite. Exemplu:

program_untested.

Aceasta ar putea fi folosit ca un gol intr-o interogare :

?- program_untested.
true.

Eventual, o modalitate mai buna de a face acest lucru ar fi sa utilizati o relatie unar:

program_status(untested).

Cu toate acestea, ideea este ca relatiile nullary exista in Prolog, ar trebui sa gasiti o utilizare pentru ei.

A se vedea, de asemenea, intrarea urmatoare pentru mai multe detalii.

Relatii si functii in matematica si in Prolog
(Daca sunteti in cautarea pentru punerea in aplicare Prolog de??functii matematice precum sin, cos, sqrt, log, exp, etc, cautati sub built-in functii.)
O relatie binara, in matematica, este un set de perechi ordonate. De exemplu, daca ne gandim cele 3 animale: mouse-ul, iepure, si oi, si "mici" relatie, apoi setul de perechi ar fi {(soarece, iepure), (mouse-ul, oi), (iepure, oaie )}. In notatia matematica, v-ar scrie, de exemplu, (soarece, iepure)? mai mici, sau mouse-ul iepure mai mici. Sau ai putea folosi un simbol in loc de mici, poate "<" - mouse-ul <iepure, sau? -? iepure mouse-ul. Acest lucru este mentionat ca o notatie infix, deoarece numele a ceea ce este scris in-intre cele doua obiecte (de soarece si iepure).

In Prolog, in schimb, in mod implicit vom folosi notatia prefix: smaller(mouse, rabbit). A se vedea op daca doriti sa definiti un operator infix intr-un program Prolog.

Acest punct de vedere al unei relatii este uneori numit de parere extensional - va puteti aseza pe deplin "masura" a relatiei, cel putin in cazul unui raport intr-un numar finit de elemente, cum ar fi noastre "mici" de exemplu. Punctul de vedere alternativ este numit intensional, in cazul in care ne vom concentra asupra sensului relatiei. In Prolog, aceasta corespunde unei norme care exprima ceea ce priveste, cum ar fi:

smaller(X, Y) :-
    volume(X, XVolume),
    volume(Y, YVolume),
    XVolume < YVolume.
Aceasta, desigur, defineste numai o semnificatie sau intensitate de smaller in raport cu sensul nespecificate de relatia volume(_,_), si sensul de <, care este definit de punere in aplicare Prolog.

Cand ajungem la non-binare de relatii, cum ar fi cele unar (cum ar fi is_a_dog(fido) ) sau cele ternare (cum ar fi gives(john, mary, book) sau between(rock, john, hard_place) ), ceea ce nu face infix nici un sens, astfel incat notatia prefix este normal. (Postfix notatia - fido is_a_dog. pot lucra pentru relatiile unar)

In timp ce noi de multe ori nu cred ca de felul acesta, o functie este un fel de relatie. Daca sunteti de gandire cu privire la functia f (x) = x 2, apoi lucru esential este ca, pentru fiecare valoare a lui x, exista o valoare a lui f (x) (adica x 2). De fapt, exista o valoare unica a lui f (x). Deci, o functie (de o singura variabila) poate fi privit ca o relatie binara, astfel incat pentru orice x relevante component in primul rand, nu este exact o pereche in relatia pe care a ca prima componenta *: perechea este (x, f (x) ). In cazul in care f (x) = x 2, sunt perechi (x, x 2) se aplica pentru fiecare valoare de x. Avem nevoie pentru a specifica ceea ce valorile aplicabile ale lui x sunt - domeniul functiei. In cazul in care domeniul este {1, 2, 3}, apoi perechile sunt {(1,1), (2,4), (3,9)}. In cazul in care domeniul este toate numerele naturale, atunci nu putem scrie extinderea functiei in totalitate, dar putem folosi o expresie set, cum ar fi {(n, n? n) | n? N}, unde N semnifica set din toate numerele naturale.

In Prolog, in ciuda faptului ca foloseste o notatie relational (cu exceptia pentru expresii aritmetice), functii sunt comune, dar a exprimat folosind notatia relationale care depinde de definitia / conventii, in paragraful anterior. In codul nostru Prolog definirea smaller(X, Y), de mai sus, relatia numit volume este de fapt o functie in scris relational. Suntem spun ca pentru fiecare obiect relevante X este o valoare XVolume care este volumul de X. Aceasta este o relatie de tip functie.

Notiunea de domeniu se aplica relatiilor, precum si functii: o definitie mai detaliata a unei relatii binare pe un set A spune ca o astfel de relatie este un subset al setului A? A de toate perechile de elemente din A A este domeniu. a relatiei. O relatie binara intre seturi A si B este un subset al A, B?. Si asa mai departe pentru relatiile ternare si dincolo. O relatie unar pe A este doar un subset al A. Astfel, is_a_dog este un subset al setului de animale de toate. Sau un subset al setului de toate lucrurile, in functie de cat de in linii mari pe care doriti sa ia in considerare conceptul de a fi un caine.

Cu toate acestea, in Prolog, domenii de relatii nu sunt abordate explicit. #, Notiunea de domeniu corespunde exact cu cea de tip, in limbaje de programare tastat cum ar fi, C, C + +, Java, Haskell, etc Prolog nu are built-in mod de izolare the definirea unei relatii (daca extensionally sau printr-o regula) intr-un anumit domeniu. Daca doriti, puteti construi tip de control in regulile, de exemplu, prin care ofera o definitie a unui tip ca o relatie unar. De exemplu, daca ai vrut sa se defineasca tipul de toate papi, ai putea sa le enumera toate, desi lista ar fi lunga:

pope(peter).
…
pope(john_paul_ii).
pope(benedict_xvi).
Apoi, obiectivul pope(X) vor verifica daca X a fost / este un Papa.

Un alt exemplu: atunci cand defineste relatia sister in Prolog, v-ar scrie, de obicei, ceva de genul:

sister(Person1, Person2) :-
    female(Person1), female(Person2),
    mother(Person1, Mother), mother(Person2, Mother),
    father(Person1, Father), father(Person2, Father),
    Person1 \== Person2.
female(Person1) si female(Person2) sunt de tip locului - fara ele, sunt definitorii sibling, nu sister. In practica, nu se poate enumera toate femeile, spre deosebire de toate papi, dar in multe cazuri, v-ar putea enumera toate cele relevante.

In unele cazuri, ati putea fi in masura sa scrie reguli imprejurimi tip de verificare. Prolog include unele predicate built-in de tip control: number(X) reuseste daca X este un numar, in timp ce integer(X) reuseste numai daca X este o parte integranta (intreg) numarul. Aici este o regula pentru a verifica daca un numar este divizibil cu 3.

div_by_3(X) :-
    X mod 3 =:= 0.

Nu exista nici o sintaxa speciala pentru a crea functii in Prolog (desi exista aranjamente speciale pentru built-in functii matematice ). Pentru a crea o functie in Prolog, va trebui sa utilizati sintaxa relatie si de a crea o "relatie care se intampla sa fie o functie". Puteti face acest lucru extensionally, la fel ca in

beats(rock, scissors).
beats(paper, rock).
beats(scissors, paper).
sau intensionally, cu o regula, ca si in functia f (x) = x 2, care ar putea fi codificate in Prolog ca aceasta (folosind numele square_of ):
square_of(X, XSquared) :-
  number(X),
  XSquared is X * X.
utilizate ca in exemplele urmatoare:
?- square_of(3.2, Y).
Y = 10.24
The number(X) de testare implicit limiteaza domeniul functiei de numere.

Retineti ca, in timp ce am definit square_of cu o utilizare functionala in minte, acesta poate fi utilizat intr-un sens relational, daca se doreste:

?- square_of(3, 9).
true.

Note de subsol:
* Daca exista, nu exact, dar cel mai putin o pereche in relatia pe care a x in calitate de membru sale in primul rand, spunem ca ceea ce este o functie partiala. O functie partiala este ca o functie care are "gauri" in ea - f (x) nu are mai mult de o valoare, dar pentru unele x in domeniul functiei, f (x) nu ar putea avea nici o valoare. Un exemplu din viata reala este eldest_child_of functie partiala, definita pe domeniul de toti oamenii adulti.

# Exista o serie de domenii de Prolog in cazul in care exista unele built-in de tip de control - de exemplu, built-in predicat < va genera un mesaj de eroare daca incercati sa-l utilizati compara un sir cum ar fi 'mouse' cu un numar cum ar fi 9.

repeat
Built-in predicat repeat in cazul in care se comporta astfel cum sunt definite prin:

repeat.
repeat :- repeat.

Astfel, repeat reuseste atunci cand primul chemat, datorita prima clauza. In cazul in care interpretul Prolog backtracks ulterior, a doua clauza ( repeat :- repeat. ) este incercat. Aceasta initiaza un nou apel la repeat, care reuseste prin intermediul prima clauza, si asa mai departe.

Pentru un exemplu practic de o utilizare a repeat, a se vedea aici.

retract, retractall
retract este un built-in meta-predicat folosit pentru a elimina fapte sau reguli din baza de date Prolog in timp ce un program este de executare. Acesta este cel mai des utilizat in parteneriat cu assert (sau una dintre rudele sale). De exemplu, programul ar putea avea emis ipoteza ca unele sau de fapt regula este corecta, se adauga la baza de date Prolog folosind assert (sau una dintre rudele sale), atunci programul exploreaza consecintele pe care presupunere, si conchide ca faptul a fost sau norma gresit. Deci, atunci programul retract e fapt sau regula.

Mai prozaic, este posibil sa aveti pur si simplu o interogare care se executa in mod repetat, in timpul unei sesiuni de prolog singur, descopera unele fapte noi in fiecare termen, dar are nevoie pentru a scapa de ele la inceputul interogarea urmatoare. Deci, din nou, retract poate fi folosit pentru a curata faptele descoperite din baza de date.

?- assert(likes(mary, pizza)).
true.
?- likes(mary, pizza).
true.
?- retract(likes(mary, pizza)).
true.
?- likes(mary, pizza).
false.
?- assert((happy(X) :- rich(X), famous(X))).
X = _G180
true.
?- retract((happy(X) :- rich(X), famous(X))).
X = _G180
true.

Nu va faceti griji cu privire la X = _G180, asta e doar SWI Prolog redenumirea variabila X cu un nume unic pentru a nu se confunda cu (diferite) variabila X ca ati putea fi utilizat in unele alte norme. Retineti, de asemenea pereche de paranteze () in jurul valorii de regula, spre deosebire de fapt.

Ce un apel pentru a retract de fapt nu este de a elimina faptul primul sau regula care se potriveste cu argumentul de a retract. Daca doriti sa eliminati, sa zicem, toate faptele cu privire la likes cu doua argumente, se pare ca si cum ar putea sa aiba pentru a apela retract in mod repetat. Nu va temeti, retractall este aici! Aceasta meta-predicat, astfel cum sugereaza si numele, se retrage toate faptele sau normele care se potrivesc cu argumentul sau unic. De exemplu:

?- assert(likes(mary, pizza)), assert(likes(john, beer)).
true.
?- listing(likes).
:- dynamic likes/2.
likes(mary, pizza).
likes(john, beer).

" :- dynamic/2 ", ne spune ca likes/2 este un built-in predicat, care pot fi modificate in timpul executiei programului (a se vedea dynamic ). Acest lucru este de a opri programul de modificarea parti neautorizate de la sine, si devenind total ne-debuggable. Exemplu continua:

?- retractall(likes(X, Y)).
X = _G180
Y = _G181 
?- listing(likes).
:- dynamic likes/2.
true.

A se vedea, de asemenea, assert. Programe care utilizeaza retract si retractall poate fi deosebit de dificil pentru a depana.

Sfat: In unele versiuni de Prolog, retractall poate esua daca nu este nimic de a retracta. Acest lucru poate parea rezonabil (desi este probabil un bug in special punerea in aplicare), dar poate ajunge in calea unei "profilactice" retractall apel pentru a va asigura ca nu exista stanga peste faptelor / norme situata in jurul valorii de calcule anterioare. Pentru a obtine in jurul valorii de aceasta, assert un fapt manechin de tipul potrivit (ceva assert(likes(dummy, dummy)), presupunand ca likes/2 este ceea ce tu incerci sa scape de), inainte de a suna retractall. SWI Prolog, de fapt, nu reuseste pe un retractall apel cu nici un fapt de potrivire / norme.

regula
O regula Prolog este o clauza, in mod normal, cu unul sau mai multe variabile in ea. In mod normal, normele au un cap, gat si corp, la fel ca in:

eats(Person, Thing) :- likes(Person, Thing), food(Thing).

Aceasta spune ca o Person eats un Thing in cazul in care Person likes Thing, si Thing este food. Retineti ca Prolog nu are nici o notiune de sensuri de eats, Person, Thing, likes, si food, astfel incat pentru Prolog regula este pur si simplu manipulare simbol abstract. Cu toate acestea, probabil autorul a normei destinate sa aiba sensul de mai sus. Ar fi posibil sa se scrie ca regula e(P, T) :- l(P, T), f(T). sau chiar xx(X1, X2) :- xxx(X1, X2), xxxx(X2). Evident, regula este mult mai usor de citit daca procedura de nume sugestive si nume de variabile sunt folosite.

Uneori, intr-o "regula", organismul poate fi gol:

member(Item, [Item|Rest]).

Aceasta spune ca postul este un membru de orice lista (al doilea argument), din care aceasta este primul membru. Aici, nici o conditie speciala trebuie sa fie indeplinite pentru a face cap adevarat - este intotdeauna adevarat.

Astfel de norme pot fi re-au exprimat astfel incat sa aiba un organism - de exemplu,

member(Item, [Head|Rest]) :- Head = Item.

Acest Prolog fortele pentru a efectua un alt pas (verificarea faptului ca Head = Item ), astfel incat este invechit.

Uneori, intr-o regula, nu ar putea sa nu variabile, sau nici unul in cap de la regula:

start_system :-
   initialise,
   invoke_system,
   finalise.

Astfel de norme tind sa aiba un stil foarte procedural, specificand in mod eficient o succesiune de etape care trebuie sa se faca in ordine. Este un aspect care este cel mai bun evitat, sau cel putin minimalizat.

A se vedea, de asemenea, faptul.

setof
Built-in predicat Prolog setof(+Template, +Goal, -Set) se leaga Set la lista de toate instantele din Template care indeplinesc obiectivul Goal.

De exemplu, avand in vedere faptele si regula:

happy(fido).
happy(harry).
happy(X) :- rich(X).
rich(harry).

rezulta ca

?- setof(Y, happy(Y), Set).
Y = _G180
Set = [fido, harry] ;
false.

Observati ca:

  • Exista doua moduri de a dovedi ca harry este happy
    • de fapt happy(harry).
    • de la regula si faptul rich(harry).
    Cu toate acestea, harry apare numai o singura data in caracter obligatoriu pentru Set ;
  • obligatorii pentru Set este in ordine sortata.

Compara:

?- bagof(Y, happy(Y), Bag).
Y = _G180
Bag = [fido, harry, harry] ;
false.
si
?- findall(Y, happy(Y), Bag).
Y = _G180
Bag = [fido, harry, harry] ;
false.

Diferentele dintre bagof si findall pe de o parte, si setof pe de alta parte, se numara faptul ca, odata cu setof, te sortate ordine si nici repetitii. (Pentru diferentele intre bagof si findall, a se vedea findall.)

setof va esua (si deci nu isi asuma obligatii Set ), in cazul in care nu exista cazuri de Template pentru care Goal reuseste - adica in mod eficient in cazul in care aceasta nu reuseste Set. ar fi gol bagof, de asemenea, nu reuseste in aceste conditii, in timp ce findall nu (se leaga variabila care este al treilea argument la lista de gol, sau, daca al treilea argument este instantiat, reuseste daca al treilea argument este lista gol).

efecte secundare
Prolog se presupune ca este o declarativ limbaj - care este, unul care specifica relatiile dintre concepte folosind fapte si normele si apoi foloseste un motor de logica sa raspunda la intrebari care se refera la aceste fapte si norme, de obicei, prin gasirea unor legaturi pentru variabile care sa permita interogari pentru a reusi.

Cu toate acestea, in "reale" Prolog, sunt incorporate in predicate care nu fac comform la acest model. Acestea includ intrari-iesiri "predicatele" cum ar fi see, seeing, seen, tell, telling, told, write, nl, prin, print, put, si a read, get, get_byte, flush_output. Toate aceste predicate reusi sau nu independent de orice aspect logic al problemei fiind rezolvata - in mod normal, de fapt, ei vor reusi daca nu exista o eroare cu privire la intrare externa / iesire sistem - de exemplu, ar putea sa nu fie posibila pentru a citi dintr-o fisier, deoarece utilizatorul nu are permisiunea de a accesa fisierul, sau deoarece fisierul nu exista.

Chiar mai mult extra-logice sunt assert, asserta, assertz si retract, retractall, care se schimba chiar programul pe care se executa.

Efectele secundare ia programelor Prolog din lume de logica stricta (ca nu taie, care schimba modul in care functioneaza motorul de inferenta in rezolvarea-o interogare). Programe cu efecte secundare sunt mai greu sa analizeze ca programele fara efecte secundare. Impactul practic de efecte secundare asupra understandabilty a programelor Prolog depinde de modul in care acestea sunt utilizate. De exemplu, folosind memoisation sa inregistreze faptele deduse, in scopul de a salva re-calculul este probabil inofensiv, dar folosind assert pentru a crea noi reguli s-ar putea, in anumite cazuri, fac depanarea unui program de langa imposibil. Utilizati efecte secundare cu grija.

Singleton variabile
SWI Prolog produce uneori un mesaj de avertizare ca aceasta:
% cat example.pl
happy(Pet) :-
   dog(Pet),
   walkies(Oet).
% prolog -s example.pl
Warning: example.pl:1:
	Singleton variables: [Oet]
…
Acest lucru va pune in alerta la faptul ca variabila Oet a fost utilizata numai o data in regula, se pare inch variabilele sunt adesea (dar nu intotdeauna), greseli de ortografie. In acest caz, Oet ar fi trebuit sa Pet.

Uneori, rapoartele Singleton variabile sunt cauzate de programator incercarea de a scrie cod de ajutor, usor de citit, ca aceasta versiune de member :

member(Item, [Item | Rest]).
member(Item, [NotItem | Rest]) :-
    \+ Item = NotItem,
    member(Item, Rest).
Prolog va raporta
	Singleton variables: [Rest]
pentru astfel de cod, deoarece restul util numele de variabila este folosita o singura data in member(Item, [Item | Rest]). Solutia este de a pune o linie de subliniere ( _ ) la inceputul acestui exemplu de Rest, inlocuind astfel member(Item, [Item | Rest]). cu member(Item, [Item | _Rest]). SWI Prolog va trata _Rest ca un tacerea: nu-ingrijire variabila si nu-l raport.

spy
Built-in pseudo-predicat spy ne permite sa urmareasca executarea unei interogari intr-un mod selectiv. Daca doriti pentru a afla despre fiecare data ca un anumit predicat este numit, va spy ca predicat: a se vedea exemplul de mai jos.

?- listing(happy).
happy(A) :-
        rich(A).
true.
?- listing(rich).
rich(fred).
true.
?- spy(rich).
% Spy point on rich/1
true.
[debug]  ?- happy(fred).
   Call: (8) rich(fred) ? creep
   Exit: (8) rich(fred) ? creep
   Exit: (7) happy(fred) ? creep
true.

Dupa cum puteti vedea, apelul la bogat este urmarit, dar nu de mult altceva. A se vedea, de asemenea, trace, urme care executarea totul.

Turn off spionaj cu nospy :

[debug]  ?- nospy(rich).
% Spy point removed from rich/1

true.

static
O procedura Prolog este static daca faptele sale / norme nu se schimba in timpul executiei programului din care fac parte. Acest lucru este implicit: cele mai multe proceduri Prolog sunt statice. Opusul statica este dinamic.

structurile
Structuri din Prolog sunt pur si simplu obiecte care au mai multe componente, dar sunt tratate ca un singur obiect. Sa presupunem ca dorim sa reprezinte o data in Prolog - datele sunt, de obicei, exprimata printr-o zi, o luna, si un an, dar considerate ca un singur obiect. Pentru a combina componentele intr-o structura unica, vom alege un functor, spun date, si folositi-l pentru a grupa impreuna componentele - pentru data de obicei exprimat la 21 martie 2004, vom scrie, probabil,

date(21, mar, 2004)
Retineti ca ordinea componentelor este alegerea noastra - am putea avea loc in scris date(2004, mar, 21) Alegerea functorului este arbitrara, de asemenea.

Componentele intre paranteze sunt mentionate ca argumente. Astfel, in exemplul de data, argumentele sunt 21, mar, si 2004.

Structuri pot fi imbricate, de asemenea - de urmatoarele grupuri exemplu, un nume si o data, poate data persoanei de nastere:

persondata(name(smith, john), date(28, feb, 1963))
Acest termen are doua argumente, fiind primul name(smith, john) si fiind al doilea date(28, feb, 1963)

A se vedea, de asemenea, Bratko, pct. 2.1.3.

reusi
O Prolog scop reuseste daca este posibil sa se verifice, fie in mod direct impotriva faptele cunoscute la Prolog, sau gasi legaturi pentru variabilele in gol care face adevaratul scop.

O interogare de succes daca fiecare din obiectivele sale reuseste.

termen
Sintactic, toate obiectele de date din Prolog sunt termeni. De exemplu, atomul mar si date, precum si structura date(2004, mar, 21) sunt termeni. Deci, sunt numerele 2004 si 21, pentru care conteaza. Astfel, in date(2004, mar, 21), functorul primar este date, aritate este 3, iar argumentele sunt 2004, mar, si 21.

In general, un termen de aritate n poate fi un atom ( functorul ), urmate de argumente n, care vor fi incluse in paranteze ( ) si separate prin virgule. Retineti ca aritate ar putea fi 0, caz in care nu exista paranteze, virgule, sau argumente. Un termen poate fi, de asemenea, un numar. Uneori, termenul poate utiliza un infix operator ca <, caz in care functorului apare intre argumentele (daca este aritatea 2) sau inainte de argument, dar fara paranteze (daca aritatea este 1).

pe termen lung cu componente colorate

Pentru + si (si ocazional ? semne), in fata argumentelor, in comentarii antet procedurii, a se vedea comentariile.

de testare de tip termen, atom, atomic, compound, float, integer, nonvar, number, var

Ar putea fi utila pentru a putea testa daca un termen este un numar sau o variabila sau altceva. Prolog ofera mai multe teste, cum ar:

Scop reuseste daca X este...
var(X) uninstantiated o variabila
nonvar(X) nu o variabila, sau este o variabila instantiat
compound(X) un termen compus - nu o variabila nelegata, si nu atomic (vezi mai jos)
atom(X) un atom, sau legat la un atom
integer(X) un intreg, sau legat de un intreg
float(X) o virgula mobila (fractionare) numarul, cum ar fi de 3,5 sau 1.0, sau legat de o - dar, daca float(X) este evaluata cu ajutorul is, atunci veti primi aceasta float
number(X) un numar, sau legat de un numar (intreg sau float)
atomic(X) un numar, sir, sau atom, sau legat de o

de testare codul
Iata cateva sfaturi pentru testarea codul Prolog.
Si aici sunt cateva sfaturi pe scris, procedurile recursive in Prolog care includ unele sfaturi pentru depanare (in exemplul 3).

urmarirea
Tracing de executare a unei interogari Prolog va permite sa vedeti toate obiectivele pe care sunt executate ca parte a interogarii, in ordine, impreuna cu sau nu reusesc. De urmarire, de asemenea, va permite sa vedeti ce masuri sa apara ca backtracks Prolog.

Pentru a activa urmarirea in Prolog, executa "gol"

?- trace.

true.

Cand ati terminat cu urmarirea, opriti-l folosind "gol"

?- notrace.

Aici este un exemplu de trace in actiune. In primul rand un cod, care calculeaza N factorial - produsul dintre numerele de la 1 la N. Prin conventie, 0 factorial este 1. N factorial este scris de multe ori N!, in cazul in care un semn de exclamare semnifica "operator de factorial". Aici este codul:

factorial(0, 1).
factorial(N, NFact) :-
N > 0,
Nminus1 is N - 1,
factorial(Nminus1, Nminus1Fact),
NFact is Nminus1Fact * N.
rule 1
rule 2
rule 2, goal 1
rule 2, goal 2
rule 2, goal 3
rule 2, goal 4
factorial(0) = 1

if N > 0, then
compute N - 1,
recursively work out factorial(N-1),
then multiply that by N

Tabelele de mai sus si mai jos nu pot afisa corect daca vizualizate intr-o fereastra ingusta. In cazul in care comentariul nu pare sa se alinieze corect cu textul la stanga de ea, incearca sa faci fereastra browser-ului mai mare.

Prolog de??dialog / urme de iesire Comentariu
prolog -s factorial.pl
blah blah blah …
?- trace.
true.
[trace]  ?- factorial(3, X).
   Call: (7) factorial(3, _G284) ? creep*
^  Call: (8) 3>0 ? creep
^  Exit: (8) 3>0 ? creep
^  Call: (8) _L205 is 3-1 ? creep
^  Exit: (8) 2 is 3-1 ? creep
   Call: (8) factorial(2, _L206) ? creep
^  Call: (9) 2>0 ? creep
^  Exit: (9) 2>0 ? creep
^  Call: (9) _L224 is 2-1 ? creep
^  Exit: (9) 1 is 2-1 ? creep
   Call: (9) factorial(1, _L225) ? creep
^  Call: (10) 1>0 ? creep
^  Exit: (10) 1>0 ? creep
^  Call: (10) _L243 is 1-1 ? creep
^  Exit: (10) 0 is 1-1 ? creep
   Call: (10) factorial(0, _L244) ? creep
   Exit: (10) factorial(0, 1) ? creep
^  Call: (10) _L225 is 1*1 ? creep
^  Exit: (10) 1 is 1*1 ? creep
   Exit: (9) factorial(1, 1) ? creep
^  Call: (9) _L206 is 1*2 ? creep
^  Exit: (9) 2 is 1*2 ? creep
   Exit: (8) factorial(2, 2) ? creep
^  Call: (8) _G284 is 2*3 ? creep
^  Exit: (8) 6 is 2*3 ? creep
   Exit: (7) factorial(3, 6) ? creep

X = 6 ;
   Redo: (10) factorial(0, _L244) ? creep
^  Call: (11) 0>0 ? creep
^  Fail: (11) 0>0 ? creep
   Fail: (9) factorial(1, _L225) ? creep
   Fail: (8) factorial(2, _L206) ? creep
   Fail: (7) factorial(3, _G284) ? creep

false.
[debug]  ?- notrace. % turn off tracing

true.
[debug]  ?- 
Invoke prolog, loading code for factorial
Greeting from Prolog
Turn on tracing

Call factorial
Trace echoes query, replacing X with a unique variable
Rule 2, Goal 1 (N > 0) is invoked
Goal 1 succeeds immediately
Rule 2, Goal 2 invoked to compute 3 - 1
and succeeds
Rule 2, Goal 3 is invoked: level 2 call to factorial(2, …)
Goal 1 again for new call to factorial
Goal 1 succeeds
New version of goal 2
succeeds
Rule 2, Goal 3 is invoked: level 3 call to factorial(1, …)
Goal 1 again
succeeds
Goal 2 again
successfully
Rule 2, Goal 3 is invoked: recursive call to factorial(0, …)
This time, Rule 1 succeeds at once.
This is Goal 4 of level 3
Compute 1 * 1 without trouble
so the level 3 factorial call succeeds
This is goal 4 of level 2
Compute 1 * 2 without trouble
so the level 2 factorial call succeeds
This is goal 4 of level 1
Compute 2 * 3 without trouble
so the level 1 factorial call succeeds

… with this binding of X - type ";" to find more solutions
Prolog backtracks looking for another solution






without success
Turn off tracing.



* Ce este aceasta "creep" de afaceri? In SWI Prolog, punerea in aplicare a acestui dictionar Prolog care utilizeaza pentru sintaxa de exemple sale, atunci cand apasati reveni la sfarsitul unei linii de urmarire, Prolog printuri "creep", pe aceeasi linie, si apoi imprima urmatoarea linie de urme de iesire de pe linia urmatoare. Apasand intoarcere produce din nou "creep" din nou si o alta linie de urmarire, si asa mai departe.

Exista alte facilitati de urmarire in SWI Prolog. Face

?- help(trace).
pentru a incepe pentru a afla despre ele.

Built-in functii Prolog nu sunt trasate - care este, interne de apeluri la lucruri ca member nu sunt explicate in detaliu de catre urmarirea lor.

true
Built-in predicat Prolog fara nici un argument, care, dupa cum sugereaza si numele, reuseste intotdeauna.

A se vedea, de asemenea, fail, repeat.

A se vedea articolul pe care nu le pasa variabile.

subliniere, tacerea: nu-ingrijire variabila
Variabila Prolog _ (subliniere) este un "tacerea: nu-ingrijire" variabila, care se va potrivi nimic (atom, numarul, structura,...). De exemplu, regula

bad(Dog) :- bites(Dog, _).

spune ca ceva ( Dog ) este rau in cazul in care Dog musca ceva. "Ceva" este reprezentat de _. Spre deosebire de alte variabile in Prolog, un gol _ poate meci de lucruri diferite in aceeasi regula. Deci, de exemplu, in cazul in care gives(From, To, Gift) este o procedura de trei loc care este valabil in cazul in care From da Gift la To, atunci

giver(X) :- gives(X, _, _).

semnifica faptul ca cineva ( X ) este un "datator" daca X da ceva la cineva - cele doua _ e nu trebuie sa se potriveasca acelasi lucru. Deci, daca gives(fred, john, black_eye). sunt stocate in baza de date Prolog, apoi regula de mai sus ne permite sa se deduca faptul ca fred este un datator.

Pentru a fi mai explicit cu privire la sensul de regula, ai putea scrie in schimb:

bad(Dog) :- bites(Dog, _Anybody).
Acest lucru indica ceea ce _ variabila este de fapt reprezinta, dar are caracteristica ca legarea de _Anybody de obicei, nu se raporteaza atunci cand Prolog gaseste o solutie. In acest raport interpreti Prolog variabilele Singleton (variabile care sunt utilizate numai o data intr-o regula - de multe ori acestea sunt cauzate de erorile tipografice in cod, care este motivul pentru care Prolog va avertizeaza despre ele) nu raporteaza variabile Singleton care incep cu _. Acest lucru este util este pe care incercati sa scape de mesaje de avertizare in codul Prolog dumneavoastra.

Regula

bad(Dog) :- bites(Dog, _Anybody).
de fapt, are un bug, in sensul ca se va potrivi _Anybody lucruri (cum ar fi dogfood) ca un caine ar putea sa muste, fara a fi "rau". Poate ca regula ar trebui sa spun in schimb:
bad(Dog) :-
    bites(Dog, Something),
    is_person(Something).
% add your own list of prohibitions - shoes, cats, …

Sisteme Prolog face uz intern de nume de variabile care incep cu o linie de subliniere, de exemplu, _G157. Acestea nu sunt "tacerea: nu-ingrijire", variabile, dar sunt alese nu sa intre in conflict cu orice nume de variabila de un programator Prolog este probabil de a utiliza.

Subliniaza, de asemenea, pot fi utilizate in mijlocul de nume de variabile sau atom, la fel ca in Intermediate_solution, likes_person - din nou, acestea nu sunt "tacerea: nu-ingrijire" variabile. Ideea este de a face un nume de variabila sau atom mai usor de citit.

unificare, =, \=
Cand ne-am scrie un gol ca X = Y in Prolog, suntem de testare pentru mai mult de egalitate simpla, in sensul matematic. Suntem de testare, daca X (care ar putea fi o variabila, un atom, sau un complex arbitrar termen lung ) se unifica cu Y (care ar putea fi, de asemenea, un atom, o variabila, sau un termen). Doi atomi, atomii inclusiv numerice, unifica in cazul in care sunt aceleasi. Doi termeni mai complexe unifica daca au aceleasi functorul si corespunzatoare acestora argumente unifica. O variabila intotdeauna se unifica cu un termen (cu conditia ca nu este in prealabil unificat cu ceva diferit), prin legare la termen Exemple.:
?- fred = fred.
true.
  
fred se unifica cu fred - acestea sunt acelasi atom.
?- X = fred.
X = fred
  
X se unifica cu fred prin legarea de X la fred.
?- X = likes(mary, pizza).
X = likes(mary, pizza).
  
X se unifica cu likes(mary, pizza) by binding X to likes(mary, pizza).
?- likes(
|        mary,
|        book(
|             title(Title),
|             author(
|                    given('Herman'),
|                    SurnameTerm)))
|  =
|  likes(
|        Who,
|        book(
|             title('Moby Dick'),
|             author(
|                    given('Herman'),
|                    surname('Melville')))).
Title = 'Moby Dick',
SurnameTerm = surname('Melville'),
Who = mary.
  
Retineti ca | caractere de la inceputul fiecarei linii sunt continuarea solicita de la Prolog, deoarece aceasta interogare a fost raspandit peste mai mult de o linie.
Title, SurnameTerm, si Who sunt obligate, in scopul de a realiza unificarea. Functori primar al termenilor pe fiecare parte a = meci, si veniturile unificarea prin potrivirea de perechi de argumente corespunzatoare, de exemplu, prin potrivirea si unificarea primul argument pe stanga, mary, cu primul argument pe dreapta, Who. Unificarea reuseste daca toate argumentele meci. Acest lucru va include recursiv potrivite argumente ale substructurilor, cum ar fi author/2 substructuri.

Scopul X \= Y reuseste daca X = Y nu ar reusi, aceasta este forma de negat =.

Utilizarea inutila a " =" la Forta Unirii

Aceasta este de fapt o problema de stil. Luati in considerare urmatoarele doua bucati alternative de cod Prolog pentru calcul maxim doua numere.

max1(X, Y, X) :- X > Y.
max1(X, Y, Y) :- X =< Y.
contra
max2(X, Y, Max) :- X > Y, Max = X.
max2(X, Y, Max) :- X =< Y, Max = Y.

Prima versiune este de preferat, in special pentru un programator novice Prolog, deoarece consolideaza modul in care functioneaza Prolog. De asemenea, nu implica inutile Max = X sau Max = Y.

Ori de cate ori scrii " = "intr-o procedura de Prolog, a revedea codul pentru a vedea daca poate scapa de" = "clauza prin inlocuirea articol de pe stanga a" = "prin elementul de la dreptul de ea, in alta parte in procedura. Daca veti face acest lucru cu max2, te max1. Uneori este posibil sa fi scris " = "cu variabila de pe dreapta, caz in care aveti nevoie pentru a inlocui in loc de articol de pe partea dreapta a" = "cu elementul la stanga de ea.

Ar trebui sa fie posibil sa facem acest lucru ori de cate ori exista o variabila (mai degraba decat o mai complex termen ), pe cel putin o parte a " = ".

Univ, =..
=.. meta-predicat, pronuntat "Univ", poate fi folosit pentru a converti o lista a caror prima post este un atom non-numerice, intr-un termen, si vice-versa. =.. De exemplu,
?- Term =.. [likes, mary, pizza].
Term = likes(mary, pizza).
sau
?- likes(mary, pizza) =.. List.
List = [likes, mary, pizza].

univ functioneaza cu operatori infix, de asemenea, desi probabil intr-un mod usor neasteptat. Doua exemple:

?- op(700, xfy, and).

true.

?- Term =.. [and, p, q].

Term = p and q

?- Expression =.. [+, 2, 3], Value is Expression.

Expression = 2+3
Value = 5

variabil
O variabila in Prolog este un sir de litere, cifre, si de subliniere ( _ ), incepand fie cu o scrisoare de capital sau cu o liniuta de subliniere. Exemple:
X, Sister, _, _thing, _y47, First_name, Z2
Variabila _ este folosit ca un "tacerea: nu-ingrijire" variabila, atunci cand nu ne minte ce valoare are variabila. De exemplu:
is_a_parent(X) :- father_of(X, _).
is_a_parent(X) :- mother_of(X, _).

Asta este, X este un parinte in cazul in care sunt un tata sau o mama, dar nu avem nevoie sa stie cine sunt tatal sau mama, pentru a stabili ca acestea sunt un parinte.

Variabilele sunt folosite in mai mult de un fel:

spatiu alb

In scris cod in Prolog sau orice alt limbaj de programare, spatiu alb (linii goale, indentarea, alinierea poate de articole legate de date) poate fi folosit pentru a face codul mai usor de urmarit. Iata cateva sugestii:

  • Pune o linie goala inainte de inceperea oricarei prolog procedura.
  • Colectii grup de fapte utilizand linii goale.
  • Uneori ajuta la linia de pana comentarii, dar nu in detrimentul de a face linii de mai mult de aproximativ 75-80 de caractere.
  • Nu puneti procedurile ajutor in mijlocul altor proceduri: separa-le inainte sau dupa procedura pe care o ajuta. In cazul in care procedura de ajutor este utilizat in procedurile de mai multe alte, este posibil sa doriti sa-l puneti chiar la capatul de toate cod.

Exemplu. In ferestrele browser-ului dimensiune moderata, exemplu negativ va avea linii de mult timp, care sunt indoite de browser-ul, si bun exemplu nu vor. In practica, ai putea face liniile din exemplul de bun, mai degraba mai mult - pana la 75-80 de caractere.

Bine Rau
% smallest(+ListOfNumbers, -Min)
% binds Min to the smallest item
% in the non-empty ListOfNumbers.
% ListOfNumbers should be instantiated
% at time of call.
smallest([FirstNum], FirstNum).
smallest([FirstNum | Rest], Min) :-
smallest(Rest, MinRest),
smaller(FirstNum, MinRest, Min).

% smaller(+First, +Second, -Smaller)
% helper procedure for smallest.
smaller(A, B, A) :-
A <= B.
smaller(A, B, B) :-
B < A.
% smallest(ListOfNumbers, Min) binds Min to the smallest item in the non-empty ListOfNumbers. ListOfNumbers should be instantiated at time of call.
smaller(A, B, A) :- A <= B.
smaller(A, B, B) :- B < A.
% This is a helper procedure for smallest.
smallest([FirstNum], FirstNum).
smallest([FirstNum | Rest], Min) :- smallest(Rest, MinRest), smaller(FirstNum, MinRest, Min).

A se vedea, de asemenea, indentarea si comentarii.


Published (Last edited): 12-10-2011 , source: http://www.cse.unsw.edu.au/~billw/prologdict.html