Doposud byly naše programy jako vytesané do kamene. Všechna fakta (kdo je rodič, kdo je muž) jsme napsali do souboru, spustili Prolog a hotovo. Pokud se narodilo nové dítě, museli jsme vypnout program, přepsat soubor a znovu spustit. To je v pořádku pro rodokmen historických králů, ale k ničemu pro hru nebo chatbota, který se má učit nové věci "za běhu".
V této kapitole se naučíme pracovat s dynamickou databází. Naučíme Prolog, aby si dělal poznámky, pamatoval si skóre, nebo se dokonce učil nová pravidla přímo během konverzace s vámi.
Představte si paměť Prologu jako dvě různé věci:
.pl. Je to jako vytištěná kniha. Můžete v ní číst, ale nemůžete do ní psát. Když program běží, tato fakta se nemění.
Abychom mohli měnit fakta za běhu, musíme Prologu nejdříve říct, že daný predikát bude dynamický. Děláme to příkazem :- dynamic na začátku souboru.
Poté používáme dvě kouzelná slova:
assert(Fakt). – Přidat. Vloží nový fakt do databáze (zapamatuje si).retract(Fakt). – Odebrat. Najde fakt v databázi a vymaže ho (zapomene).
Představte si, že hrajete hru. Hrdina chodí po světě a sbírá předměty. Musíme si pamatovat, co má v batohu.
% 1. Řekneme Prologu, že 'mam' se bude měnit
:- dynamic mam/1.
% Na začátku nemáme nic (nebo můžeme napsat: mam(meč).)
% Pravidlo pro sebrání věci
seber(Vec) :-
assert(mam(Vec)), % Přidáme fakt do paměti
write('Sebral jsi '), write(Vec), nl.
% Pravidlo pro zahození věci
zahod(Vec) :-
retract(mam(Vec)), % Zkusíme fakt vymazat
write('Zahodil jsi '), write(Vec), nl.
zahod(Vec) :- % Co když tu věc nemáme? (retract selže)
write('Nemůžeš zahodit '), write(Vec), write(', protože ji nemáš!'), nl.
% Výpis inventáře
inventar :-
write('Máš u sebe:'), nl,
mam(X), % Najdi něco, co mám
write('- '), write(X), nl,
fail. % Vynuť backtracking, aby našel další věci
inventar. % Konec (když už nic nenajde)
Jak to funguje v konzoli:
?- seber(klic).
Sebral jsi klic.
true.
?- mam(klic).
true.
?- zahod(klic).
Zahodil jsi klic.
true.
?- mam(klic).
false.
Když přidáváte fakt, kam se zařadí? Na začátek nebo na konec? Někdy je to jedno (inventář), ale někdy je to klíčové (pravidla, která se zkouší popořadě).
asserta(Fakt) – Přidá na ZAČÁTEK (A = Alpha, první). Prolog tento fakt najde jako první.assertz(Fakt) – Přidá na KONEC (Z = Omega, poslední). Prolog tento fakt najde až nakonec. (Obyčejný assert se obvykle chová jako assertz).Prolog je jedním z mála jazyků, kde je hranice mezi "daty" a "kódem" velmi tenká. Když použijete assert, doslova měníte program, který běží. Můžete přidávat nejen fakta, ale i celá pravidla! To umožňuje vytvářet systémy, které se učí ze zkušenosti.
:- dynamic a pokusíte se použít assert na nějaký predikát? (Prolog vyhlásí chybu o modifikaci statické procedury).asserta místo assertz? (Například když chcete přidat výjimku z pravidla, která se má zkontrolovat před obecným pravidlem).kontakt/2.pridej(Jmeno, Cislo).smaz(Jmeno).jmenuji_se(Jmeno), které si zapamatuje jméno uživatele (pomocí assert).ahoj, které zkontroluje, jestli už zná jméno. Pokud ano, pozdraví jménem ("Ahoj Petře!"). Pokud ne, zeptá se "Jak se jmenuješ?" a zavolá jmenuji_se.