Vítejte zpět v detektivní kanceláři Prologu! V minulé kapitole jsme se naučili, jak Prologu "říct", co je pravda, pomocí atomů a faktů. Ale co když nevíme, co přesně hledáme? Co když chceme říct "NĚKDO" nebo "NĚCO"? Představte si, že jste Sherlock Holmes a potřebujete se zeptat: "Kdo je otcem Barta?" nebo "Co má rád Homer?". K tomu slouží proměnné – naše klíčové nástroje pro kladení otázek a hledání odpovědí.
Ale pozor! Pokud už máte zkušenosti s programováním v jazycích jako Java nebo Python, připravte se na další "kulturní šok". Proměnná v Prologu funguje úplně jinak. Mnoho studentů zde dělá chybu, protože si myslí, že proměnná je všude stejná. Není. Pochopení tohoto rozdílu je naprosto klíčové pro to, abyste Prologu skutečně porozuměli.
V jazyce Java (nebo C++) si proměnnou můžete představit jako **pevně danou krabici**. Musíte předem říct, co v krabici bude a jaký má typ. Je to jako krabice s nápisem "POUZE CELÁ ČÍSLA".
int x = 5;
Říkáte: "Vytvoř krabici jménem X. Tato krabice je vyrobena z kovu a vejdou se do ní POUZE celá čísla. Teď tam dej pětku." Pokud tam zkusíte dát text "Ahoj", program spadne. Krabice má pevný tvar a obsah můžete měnit (dát tam 6), ale typ ne. Je to jako mít krabici na jablka – nemůžete do ní dát hrušky, aniž byste ji změnili.
V Pythonu je to volnější. Proměnná není krabice, ale spíše **nálepka nebo ukazatel**. Můžete ji kdykoli přilepit na jinou věc.
x = 5
x = "Ahoj"
Říkáte: "Nalep nálepku se jménem X na číslo 5." Pak můžete nálepku strhnout a nalepit ji na text "Ahoj". Proměnná je jen odkaz, který se může měnit a ukazovat na cokoliv. Je to jako mít nálepku "Moje oblíbená věc" a přelepovat ji z jablka na hrušku.
V Prologu je to úplně jinak. Proměnná v Prologu (vždy začíná Velkým písmenem, např. X, Kdo, Vysledek) je jako **prázdná skleněná krabice s jmenovkou, která se po prvním naplnění zalepí**. Na začátku je prázdná (neinstanciovaná) – představuje neznámou, kterou hledáme.
Jakmile Prolog najde hodnotu, která "pasuje" (pomocí procesu zvaného unifikace, o kterém si povíme za chvíli), tato hodnota se do proměnné "vloží". A teď to nejdůležitější: krabice se **zalepí**. Už to **nemůžete vyměnit** v rámci jednoho dotazu nebo pravidla. Tomu se říká **Jednorázové přiřazení (Single Assignment)**. Nemůžete říct X = 5 a na dalším řádku X = 6. To by byla logická lež, protože X nemůže být zároveň 5 i 6.
Toto je další velmi důležitý rozdíl! Proměnná v Prologu existuje **pouze uvnitř jednoho pravidla** (nebo jednoho dotazu). Není globální. Představte si to jako jména studentů v různých třídách. Student "Petr" v 1.A nemá nic společného se studentem "Petr" v 2.B, i když se jmenují stejně.
otec(X, Y) :- rodic(X, Y), muz(X).
deda(X, Y) :- otec(X, Z), rodic(Z, Y).
Proměnná X v pravidle otec nemá NIC společného s proměnnou X v pravidle deda. Jsou to dvě různé "krabice", které se náhodou jmenují stejně. Jakmile Prolog dokončí práci s pravidlem, "krabice" se zahodí a její obsah se zapomene.
Někdy nás hodnota proměnné nezajímá. Chceme jen vědět, jestli "někdo" nebo "něco" existuje, ale je nám jedno kdo nebo co. K tomu slouží **anonymní proměnná**, která se značí podtržítkem _.
_ je považován za jinou proměnnou.
?- rodic(homer, _).
Tím říkáme: "Je Homer rodičem *někoho*?" Je nám jedno koho. Prolog odpoví true, pokud najde alespoň jedno dítě. Nezatěžuje paměť ukládáním jména dítěte, protože jsme mu řekli, že nás to nezajímá. Je to jako když se ptáte: "Je tu *někdo* doma?", a ne "Kdo je doma?".
Když napíšeme X = karel, Prolog neprovádí "přiřazení" jako v matematice (že by do X uložil hodnotu). On provádí **unifikaci**. Unifikace je srdcem Prologu. Je to proces, kdy Prolog se snaží, aby dvě věci (termy) byly stejné, a pokud to jde, najde hodnoty pro proměnné, které to umožní.
Představte si unifikaci jako **detektiva, který hledá shodu**. Máte dva otisky prstů a detektiv se snaží najít, zda patří stejné osobě, a pokud ano, kdo to je.
X = karel. -> OK. X je prázdné, tak do něj "vložím" atom 'karel'. Teď jsou si rovny.karel = karel. -> OK. Jsou stejné.karel = petr. -> CHYBA (Fail). To nikdy nebude pravda. Atomy jsou různé, nelze je unifikovat.X = Y. -> OK. X a Y jsou nyní propojené. Jsou to dvě jmenovky na jedné prázdné krabici. Když se později instancuje X, instancuje se i Y.bod(X, 5) = bod(2, Y). -> OK. Prolog porovná struktury. Zjistí, že X musí být 2 a Y musí být 5.Příklad 4.1: Dotaz s proměnnou
Máme fakta:
rodic(homer, bart).
rodic(homer, lisa).
rodic(marge, bart).
rodic(marge, lisa).
A teď se zeptáme našeho Prolog detektiva:
?- rodic(homer, X).
Co se ptáme: "Kdo je dítětem Homera?"
Jak Prolog "myslí":
rodic(homer, NĚCO).rodic(homer, bart).homer sedí. A vidí, že na místě X je bart.X = bart.X = bart.Pokud stisknete středník (;), řeknete Prologu: "Dobře, to je jedna odpověď, ale existuje ještě nějaká?"
rodic(homer, NĚCO).rodic(homer, lisa).X = lisa.X = lisa.Pokud stisknete středník znovu, Prolog už další shody nenajde a odpoví false.
V Prologu proměnné nejsou místa pro ukládání hodnot, které se mění. Jsou to spíše "otazníky" ve vašich dotazech a pravidlech. Prolog se snaží najít takové hodnoty pro tyto otazníky, aby celé tvrzení bylo pravdivé. Tento proces hledání shody a přiřazování hodnot se nazývá unifikace a je základem veškerého logického odvozování v Prologu.
X = X + 1? Co by to znamenalo z pohledu logiky a unifikace?_? Vymyslete si vlastní příklad z běžného života nebo hry.barva(cervena) = barva(modra). Proč to selže?true, false nebo instancuje proměnné):
X = 10, X = 20.A = B, B = c.bod(X, 5) = bod(2, Y).barva(zelena) = X.barva(X) = barva(modra).auto(znacka(skoda), model(octavia)) = auto(znacka(X), model(Y)).