# Neprocedurální programování - neprocedurální jazyky nemají přiřazovací příkazy - logické programování - funkcionální programování - funkce a jejich skládání - funkce jsou „matematické“, nemají vedlejší efekty - hlavní funktor – ten, co je nejvíc vlevo - predikát – funkce, která odpovídá ANO/NE - Prolog lze psát ve VS Code - rozšíření New-VSC-Prolog - pravé tlačítko – load document - `:-` jako implikace zprava doleva - příkaz `make.` zajistí rekompilaci - vyhodnocení pravidla probíhá průchodem do hloubky (DFS) - v Prologu záleží na pořadí - středník jako OR, čárka jako AND - konjunkce (čárka) má přednost - operátor nerovnosti (respektive neunifikovatelnosti) `\=` - kvantifikátory se explicitně nepíšou - pokud je proměnná jenom vpravo, je kvantifikovaná existenčně - pokud je proměnná na obou stranách, je kvantifikovaná obecně - s negací je obecně trochu problém - proměnné uvozené podtržítkem a pokračující čísly používá interně Prolog (tedy je lepší, když je nepoužíváme) - lze používat infixovou notaci - lze přetěžovat funktory - proměnné začínají velkým písmenem - ukončení příkazové řádky – `halt.` - „konzultace“ (kompilace) souboru `a.pl` – `consult(a).` - `make.` překompiluje klauzule, které se od minula změnily - `muz(sokrates).` … je Sokrates muž? - stisknutím středníku (u složeného výrazu) vynutíme selhání – Prolog zkouší další možnosti - `manzele(X,Y) :- manzele(Y,X).` není správný přístup, způsobí to nekonečný cyklus - např. dotaz `manzele(jina, karel_iv).` (kde `jina` neexistuje) nikdy nedoběhne - v případě neúspěchu se provede unifikace – ta prohodí pozice (ale to se postupně provádí donekonečna) - … - pracujeme s termy - term je strukturovaný typ s více položkami - v procedurálním jazyce by to odpovídalo typu záznam - položky jsou identifikovány jménem - ve složeném termu jsou položky identifikovány polohou - fakt - unifikace - základní operace na termech - unifikací `datum(D1, M1, 2024) = datum(D2, unor, R2).` je… - D1 = D2 - M1 = unor - R2 = 2024 - unifikaci vyvolá operátor = - operátor `\=` vrátí true, pokud termy nelze unifikovat - `guitracer.` - rekurze - `predek(X,Y) :- rodic(X,Y).` - `predek(X,Z) :- rodic(X,Y), predek(Y,Z).` - tenhle predikát efektivně počítá potomky, ne předky - napíšeme komentář `% predek(+Predek, ?Potomek)` - znaménko `+-` označuje, že argument může obsahovat volné proměnné - lepší predikát - … - axiomatizace přirozených čísel - deterministická a nedeterministická implementace porovnání - nedeterminismus jako mocný nástroj - seznamy - rekurze se dobře dělá tak, že řeším obecnější problém - otáčení seznamu pomocí akumulátoru – v základním kroku (fakt) zkopíruju akumulátor do výsledné proměnné - predikát append - predikáty include a exclude – až příště - programování s omezujícími podmínkami - `use_module(library(clpfd)).` - obecnější aritmetické operátory, začínají znaménkem `#` - predikáty vyšších řádů - call - maplist - foldl (reduce) - seznam s volným koncem - řez - používat s mírou - červený – mění deklarativní význam programu - zelený – nemění deklarativní význam programu, pouze odřezává neperspektivní větve výpočtu - negace --- - funkcionální fronta - Přední/Zadní - Zadní část je otočená - odebírám v konstantním čase ze začátku - v konstantním čase přidávám na konec fronty (těsně za lomítko) ## Haskell - volání funkce má největší prioritu - záporná čísla je nutné psát do závorky (opět kvůli prioritě) - informace o funkci pomocí `:i` - z funkce můžu udělat operátor pomocí zpětných apostrofů \` - chceme mít funkce definované pro všechny hodnoty definičního oboru – proto Haskell obsahuje pouze if then else (a neobsahuje if then) - soubor Prelude.hs obsahuje jakoby základní knihovnu - `:quit` ukončí prostředí - `:?` otevře nápovědu - `:load soubor.hs` načte soubor - také lze `:l` - pomocí `:r` (reload) se soubor znova načte - `:type vyraz` vypíše typ výrazu - `:set +t` nastavení options, např. výpis typu - `:set +s` … vypíše paměť a čas