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
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.
Nu exista intrari (inca) pentru literele J, K, X, Y, Z.
append 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 ?- 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
arg, termen. | 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 + 2in cazul in care
Y este o variabila deja legat la o valoare numerica, sau poate un obiectiv compararea aritmetica ca aceasta: X > Y * ZIata 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.
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 LINUXin * C1 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 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.
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 ( _ ). []. 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. <--->, ..., ===>. 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. +, -, *, /, <, >, =, :, ., &, _, 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 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 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.
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 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.
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.
:-. 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. abs, atan, ceiling, cos, exp, float, floor, log, round, sign, sin, sqrt, tan, truncate | 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.41421Comparati 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.41421Unele 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
. "). 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.
%. 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.
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. ![]()
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.
| 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. 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 ?- 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. ?-
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.
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.
!, 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. Exemplu: Sa presupunem ca avem urmatoarele fapte:
teaches(dr_fred, history). | studies(alice, english). |
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. (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.
dynamic 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.
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.
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 A se vedea, de asemenea, true, repeat, schema de intrare.
findall 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.
tell, telling, told, see, seeing, seen, append/1 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 likes(mary, pizza), likes este functor. Intr-o structura mai complexa, cum ar fi persondata(name(smith, john), date(28, feb, 1963))
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.
?- 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 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.
:-. 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 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->/2se 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;/2si->/2actioneaza 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.
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.
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.
read, end_of_file, get, get_byte, getc, flush_output 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.
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*Wsau
X*Y =:= Z*Win 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 instantiatedComparati acest lucru cu:
?- Y = 3, X is Y + 1. Y = 3, X = 4.
[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 | []] 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 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 ?- 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... _G309, _G310, _G313, etc reprezinta biti a listei Y pe care le-am nici o informatie despre. A se vedea, de asemenea, backtracking.
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.

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? 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 |
:-, utilizat intr-un Prolog regula pentru a separa capul de corp. De obicei, ca si cum ar citi. Astfel a :- b, c.
a (este adevarat) in cazul in care b si c (sunt adevarate).
\+ 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.
number(–) 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 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 :- 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)).
| 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.
; 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:
; 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
Xestehappy3dacaXeste atractiv, iarXeste 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, sihappy3sunt 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.
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. Aici, doua clauze, impreuna, definesc o conditie pentru ca cineva sa fie o societate-mama - impreuna ele formeaza o procedura.is_a_parent(Parent) :- father_of(Parent, _Child). is_a_parent(Parent) :- mother_of(Parent, _Child).
A se vedea, de asemenea, subliniaza, pe motiv pentru a pune o linie de subliniere ( _ ), caracterul in fata variabilei _Child.
?- prompt, separate prin virgule, si terminat cu un punct ( . ). De exemplu, ?- lectures(john, Subject), studies(Student, Subject). 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.
member procedura : Cea de a doua clauza este in mod clar recursiv -member(Item, [Item|Rest]).
member(Item, [_|Rest]) :- member(Item, Rest).
member are loc atat in cap si corp. O procedura recursiv poate lucra din cauza a doua lucruri: 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.) 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.2si 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 ),
Sum 1 is First 1 + SumOfRest 1. Sum 1 is First 1 + SumOfRest 1. |
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.
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.
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:
Apoi, obiectivulpope(peter). … pope(john_paul_ii). pope(benedict_xvi).
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.24The
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 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 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.
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 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:
harry este happy happy(harry). rich(harry). harry apare numai o singura data in caracter obligatoriu pentru Set ; 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).
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.
% 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 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.
date, si folositi-l pentru a grupa impreuna componentele - pentru data de obicei exprimat la 21 martie 2004, vom scrie, probabil, Retineti ca ordinea componentelor este alegerea noastra - am putea avea loc in scrisdate(21, mar, 2004)
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.
O interogare de succes daca fiecare din obiectivele sale reuseste.
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).
Pentru + si – (si ocazional ? semne), in fata argumentelor, in comentarii antet procedurii, a se vedea comentariile.
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:
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:
| 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] ?- | |
Exista alte facilitati de urmarire in SWI Prolog. Face
?- help(trace).pentru a incepe pentru a afla despre ele.
true _ (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. 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.
=, \= 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.: 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 " = ".
=.. =.. 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
_ ), incepand fie cu o scrisoare de capital sau cu o liniuta de subliniere. Exemple: X, Sister, _, _thing, _y47, First_name, Z2 _ este folosit ca un "tacerea: nu-ingrijire" variabila, atunci cand nu ne minte ce valoare are variabila. De exemplu: 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.is_a_parent(X) :- father_of(X, _).
is_a_parent(X) :- mother_of(X, _).
Variabilele sunt folosite in mai mult de un fel:
likes(A,B) :- dog(B), feeds(A,B). A si B apar pe ambele parti ale gatului simbol - aspectul de aceeasi variabila in doua (sau mai multe locuri) in vigoare spune ca, atunci cand variabila este legat la o valoare, aceasta trebuie sa fie legate la aceeasi valoare in toate locurile pe care acesta apare intr-o regula data. _1, _2, _3, etc Acesta este motivul pentru variabile cu nume ca aceste randul sau, uneori pana in mesaje de eroare atunci cand programul Prolog merge prost. ?- studies(X, 9311). Prolog raspunde prin gasirea toate valorile pentru X pentru care studies(X, 9311) este adevarat, si le listarea succesiv, de exemplu, X = fred ; X = jane ; X = abdul ; X = maria ;
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) | % smallest(ListOfNumbers, Min) binds Min to the smallest item in the non-empty ListOfNumbers. ListOfNumbers should be instantiated at time of call. |
A se vedea, de asemenea, indentarea si comentarii.