Zanke v prologu
Iz E-študij, proste zakladnice študentskega znanja
rekurzija: z avtomatskim vračanjem(findall)
Če izvedemo spodnji program, se nam zacikla. findall_napacno(X,Cilji,S) :-
call(Cilji), asserta(podatek(X)), findall_napacno(X,Cilji,S).
Vsebina |
Repeat
Repeat vedno uspe (pri avtomatskem vračanju se izvajanje vedno odbije nazaj naprej).
repeat. repeat :- repeat.
Fail
Fail povzroči nasprotno kot repeat, izvajanje nikoli ne uspe in vedno dobimo avtomatsko vračanje.
Zato lahko enostavno povzročimo neskončno zanko:
?- repeat, fail.
Odločanje
Imamo neskončno zanko dokler ne dosežemo izstopnega pogoja (konec):
delaj_iterativno :-
repeat,
write(' vtipkaj ukaz: '),
read(Ukaz),
odloci(Ukaz).
odloci(konec).
odloci(Ukaz):-
izvrsi(Ukaz),!,
fail.
Fibbonacijevo zaporedje
fib_hitri_iterat(0,1).
fib_hitri_iterat(N,F):-
assert(fib_st(1,1,1)), %inicializacija
repeat,
retract(fib_st(Stevec,F1,F2)), % dobi
(Stevec = N, !, F = F2; %robni pogoj
F3 is F1 + F2,
Stevec1 is Stevec + 1,
assert(fib_st(Stevec1,F2,F3)), % shrani nove vrednosti
fail). %vse skupaj ponovi
Primeri uporabe zank
?- findall(X,otrok(X,Y),S). S= [tine,metka,metka]; no
?- bagof(X,otrok(X,Y),S. %setof(X,otrok(X,Y),S) Y = tone %brez duplikatov S = [tine,metka]; %sortira Y = micka S = [metka]; no
?- element(X,[a,b,c,d]),write(X),write(','),fail. a,b,c,d no
?- element(X,[a,b,c,d]),write(X),write(','),fail;true. a,b,c,d yes
spremeni_it(S,P,NS) :-
findall(NX,
(element(X,S),
Tr =.. [P,X,NX],
call(Tr)),
NS).
Soda števila
soda(S,Soda) :- findall(X, (element(X,S),X mod 2 =:= 0), Soda).
Seznam števil na intervalu
interval(Min,Max,S) :- findall(X,med(Min,Max,X),S).
interval(5,10,S). S = [6,7,8,9].
Spremeni iz seznama elementov v množico (izloči duplikate).
setof(X,element(X,[a,d,e,f,c,e,b,d]),S). S = [a,b,c,d,e,f] yes
Presek 2 množic
setof(X,(element(X,[a,b,e]),(element(X,[b,d,e,f])),S). S = [b,e] yes
Želimo imeti zanko, ki za vse X-e iz znanega seznama izvede določeno operacijo:
for_X_in_S_do_rek(_,[],_). for_X_in_S_do_rek(X,[X|S],Cilji) :- call((Cilji,!,fail)). for_X_in_S_do_rek(X,[_|S],Cilji) :- for_X_in_S_do_rek(X,S,Cilji).
Alternativno z uporabo element:
for_X_in_S_do_it(X,S,Cilji) :- element(X,S), call((Cilji,!,fail)). for_X_in_S_do_it(_,_,_).
?- for_X_in_S_do_it(X,[a,b,c,d],(write(x),write(','))).
a,b,c,d,
yes