Prolog - jak działa rekurencja?

0

Witam,
mógłby mi ktoś na prostym przykładzie wytłumaczyć jak działa rekurencje w prologu ?

złącz([ ], L, L).
złącz([X|L1], L2, [X|L3]):- złącz(L1, L2, L3).

Załóżmy, że wywołujemy złącz([a,b,c],[d,e],L3]).

Rozumiem, że 1 linijka to warunek zakończenie rekurencji. Pusta lista dodana do listy L daje tą samą listę.
W 2 linijce nie mam pojęcia co się dzieje ;p

Rozumiem, że dzielimy listę L1 na głowę X (a) i ogon czyli nowe L1 (b,c). Z L2 nic nie robimy, a do L3 dodajemy X ? I potem próbujemy łączyć, lista L1 nie jest pusta więc znowu L1 dzielimy na X (b) i ogon L1 (c) i do L3 dodajemy X otrzymując a,b ? Tylko kiedy dodajemy L2 do całej listy ?

Jakby ktoś wytłumaczył mi działanie tych 2 linijek krok po kroku na tym przykładzie to byłbym wdzięczny bardzo.

1

Myśl deklaratywnie, nie imperatywnie (btw. przemianowałem złącz na concat, brzmi ładniej):

concat([ ], L, L).

pusta lista dodana do dowolnej listy daje tą listę (to co napisałeś).

concat([X|L1], L2, [X|L3]) :- concat(L1, L2, L3).

Lista [X|L1] (zaczynająca się od X i kończąca listą L1), połączona z listą L2 daje listę zaczynającą się od X i kończącą na L3 - gdzie lista L3 jest połączeniem list L1 i L2.
To akurat wynika bardzo ładnie z kodu, spróbuj przeczytać to kilka razy to może Cię olśni.

Jeszcze może rozpisane spróbuj rozpisać jak to działa dla jakiegoś przykładu (zazwyczaj pomaga, chociaż w prologu może być to ciężko ładnie rozpisać w punktach - bardziej drzewem czy coś).

Zaletą myślenia deklaratywnego jest to, że nie traktujesz zawsze jednego parametru jako wartości zwracanej, bo nie zawsze tak jest (w dokumentacji jest od typu parametrów nawet specjalna notacja) ;):

1 ?- concat([1, 2, 3], [4, 5, 6], X).
X = [1, 2, 3, 4, 5, 6].

2 ?- concat([1, 2, 3], X, [1, 2, 3, 4, 5, 6]).
X = [4, 5, 6].

3 ?- concat(A, B, [1, 2, 3, 4]).
A = [],
B = [1, 2, 3, 4] ;
A = [1],
B = [2, 3, 4] ;
A = [1, 2],
B = [3, 4] ;
A = [1, 2, 3],
B = [4] ;
A = [1, 2, 3, 4],
B = [] ;
false.
0

Ok, dzięki. To już rozumiem tylko dalej nie mogłem sobie wyobrazić po kolei jak to działa. Śledzenie w SWI-Prolog mi w tym trochę pomogło.

[trace] 3 ?- złącz([a,b],[c,d],L3).
 * Call: (6) złącz([a, b], [c, d], _G680) ?
 * Call: (7) złącz([b], [c, d], _G759) ?
 * Call: (8) złącz([], [c, d], _G762) ?
 * Exit: (8) złącz([], [c, d], [c, d]) ?
 * Exit: (7) złącz([b], [c, d], [b, c, d]) ?
 * Exit: (6) złącz([a, b], [c, d], [a, b, c, d]) ?
L3 = [a, b, c, d].

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0