Vítejte u jedné z nejzajímavějších a nejsilnějších kapitol celé knihy. Pokud jste někdy viděli film Inception (Počátek), kde byl sen uvnitř snu, který byl uvnitř dalšího snu, pak už máte představu o tom, co je to rekurze. Prolog nemá klasické cykly jako for nebo while, které možná znáte z jiných jazyků. Místo toho používá rekurzi – elegantní způsob, jak definovat něco pomocí sebe sama. Je to klíč k řešení složitých problémů pomocí jednoduchých pravidel.
Rekurze nastává, když pravidlo ve svém těle volá samo sebe. Představte si ruskou panenku matryošku. Otevřete největší panenku a uvnitř je další, stejná, jen menší. Otevřete tu menší a je tam ještě menší. A tak dále. Kdy to skončí? Až narazíte na tu nejmenší, která už se nedá otevřít. Té nejmenší říkáme základní případ.
Vraťme se k naší rodinné databázi. Víme, kdo je rodič. Ale kdo je můj předek? Předek je můj rodič, nebo rodič mého rodiče, nebo rodič rodiče mého rodiče... Vidíte ten vzor?
V Prologu to zapíšeme dvěma pravidly:
% 1. Základní případ: Můj přímý rodič je můj předek.
predek(X, Y) :- rodic(X, Y).
% 2. Rekurzivní krok: Předek je rodič někoho (Z), kdo je už mým předkem.
predek(X, Y) :- rodic(X, Z), predek(Z, Y).
Představte si řetěz: Já -> Táta -> Děda -> Praděda.
true.Pojďme počítat. Matematický faktoriál čísla N (značíme N!) je součin všech čísel od 1 do N. Např. 5! = 5 * 4 * 3 * 2 * 1 = 120.
Rekurzivní definice:
V Prologu:
factorial(0, 1). % Základní případ: Faktoriál 0 je 1.
factorial(N, Vysledek) :-
N > 0,
N1 is N - 1, % Zmenšíme problém (o 1)
factorial(N1, Mezivysledek), % Rekurzivní volání (vyřeš menší problém)
Vysledek is N * Mezivysledek. % Spojíme výsledek
Jak to funguje v paměti (Zásobník/Stack):
Představte si to jako hromadu talířů v jídelně. Každé volání funkce přidá talíř nahoru. Nemůžeme vyřešit spodní talíř (5!), dokud nevyřešíme ten nad ním (4!).
factorial(3, X). Prolog si pamatuje: "Musím vynásobit 3 * výsledek faktoriálu 2". (Přidá talíř)factorial(2, X). Prolog si pamatuje: "Musím vynásobit 2 * výsledek faktoriálu 1". (Přidá talíř)factorial(1, X). Prolog si pamatuje: "Musím vynásobit 1 * výsledek faktoriálu 0". (Přidá talíř)factorial(0, X). ZÁKLADNÍ PŘÍPAD! Výsledek je 1. (Odebere talíř)1 * 1 = 1. (Odebere talíř)2 * 1 = 2. (Odebere talíř)3 * 2 = 6. (Odebere talíř)
Rekurze je o tom, že velký a složitý problém rozdělíme na menší kopii téhož problému. Pokračujeme v dělení tak dlouho, dokud není problém tak malý (základní případ), že ho vyřešíme okamžitě. Pak poskládáme výsledky zpátky dohromady.
factorial(0, 1).? Zkuste si to představit na hromadě talířů.mocnina(X, N, Y), které spočítá X na N-tou.
fib(N, X), které najde N-té číslo v řadě. (Pozor: Budete potřebovat dva základní případy pro 0 a 1).