Procedurální a neprocedurální programování

Procedurální programování – uveďte příklady programovacích jazyků pro procedurální programování, popište členění zdrojového kódu v různých programovacích jazycích.

Kód v procedurálním jazyce je členěný do funkcí. V obvyklém jednoduchém případě se program skládá prostě ze spousty funkcí, které se můžou volat libovolně navzájem. Taky si nikdo neláme hlavu s proměnnými: pokud je možné z proměnné číst, můžete ji i zapisovat. S globálními proměnnými může pracovat každá funkce bez rozdílu. Pokud mají některé proměnné složitější obsah, měli byste k nim přistupovat pomocí obslužných funkcí, které byste si měli napsat; programovací jazyk vás k tomu ale nenutí.

Vzorové v tom ohledu jsou jazyky C a Pascal. (Ještě o něco obecnější pojem je imperativní programování. Například Assembler a Brainfuck jsou jazyky imperativní, ale nejsou procedurální. Na druhou stranu bacha, určitě nejsou neprocedurální). Mezi procedurální jazyky patří i většina objektově orientovaných, ale vlastně jsou to myšlenkové směry, které spolu nemusí souviset.

Neprocedurální programování – uveďte příklady programovacích jazyků pro neprocedurální programování, v čem spočívá neprocedurální programování a na jaké úlohy se hodí.

Nabízí se samozřejmě spousta možností, jak to "udělat jinak". Stručně shrnu aspoň ty znalosti o neprocedurálních jazycích, co mě naučili ve škole.

Hezkým zástupcem funkcionálního programování je jazyk Haskell. Základní myšlenka asi napadla každého programátora: když máme nějaké proměnné a napíšeme třeba y = x+10, bylo by hezké, kdyby se y nenastavilo na pevnou hodnotu, ale změnilo se pokaždé, když změníme x. Rovnice se vlastně nevyhodnotí, jazyk si jen poznamená, že platí tenhle vztah a y dopočítá podle potřeby až ve chvíli, když se na něj někdo zeptá. Aby to dobře mohlo fungovat, nesmí mít vyhodnocování funkcí žádné vedlejší účinky (tedy nemůžeme mít v programu ani žádné proměnné v obvyklém smyslu slova) a funkce pokaždé musí navracet totéž. Jednou z výhod je, že kompilátor se může sám rozhodovat, co vyhodnotit kdy a které výsledky cachovat. Možná to udělá i líp než člověk.

Programy v neprocedurálních jazycích nemusí být nutně pomalé. Bývají to jazyky kompilované a vyvíjí je týmy vzdělaných informatiků. Protože ale neříkáme přímo, co má počítač dělat, může být hodně těžké říct něco o časové složitosti; v některých případech je sice jasná, jindy nám ale nezbývá než kompilátoru věřit.

Taky docela často se používá jazyk Lisp (nebo Scheme (jeho dialekt (něco jako odnož))). Ten se nedrží zmíněné zásady ohledně funkcí tak pečlivě; funkcionální je hlavně v tom, že je v něm obvyklé předávat různé funkce jako parametry dalším funkcím. Používá se většinou na psaní skriptů a to si říká o spíše imperativní přístup. Je velmi proslulý svou obludnou syntaxí. (Mimochodem, existuje jazyk, který se skládá jen ze samých závorek (ale to už je jenom fór (parodie na Lisp) od nějakých znuděných hackerů (z Japonska))).

Za funkcionální programování se považuje už samo o sobě, když předáváte funkci jako parametr jiné funkci. V Ruby se to většinou řeší jenom pomocí {anonymního bloku kódu}; pokud trváte na funkci, musíte použít trochu zběsilý zápis:

["avokádo", "banán", "cukrová řepa", "durian"].sort_by(&:length)

V jiných jazycích považovaných za zcela procedurální to většinou jde taky. Třídit pole na základě nějaké funkce (hodnotící nebo porovnávací) je normální i v C++.

Další věc je deklarativní programování: popíšeme vztahy, které zaručeně mají platit, a pak se prostě zeptáme na výsledek. Hezkou ukázkou je jazyk SQL, který byste měli umět na otázku 24.

Výrazně podivnější je jazyk Prolog. Ten nepracuje s řádky v tabulkách, ale s nějakými abstraktními hodnotami: vlastně ani nevíme, co jsou za datový typ. Splňují vlastně jen to, že jsou samy sebou: X = X, fn(g(X), Y) = fn(g(X), Y). Vůbec nemusíme říct, co jsou funkce fn a g zač.

Prologu můžeme popsat nějaké vztahy, o kterých víme, že platí. Například, že lítá to, co má peří: lita(X) :- ma_peri(X). a dvě věci, které peří mají: ma_peri(kachna). ma_peri(perina). Potom se můžeme zeptat:

?- lita(X).

a Prolog poslušně zkusí postupně najít všechny možnosti:

X = perina ;
X = kachna.

V tomhle případě to bylo triviální, ale jindy to může zabrat velké množství pokusů a omylů. Sice se většinou dá obdobný program v jiných jazycích psát účinněji, ale Prologovské programy můžou být fantasticky stručné. Hodí se tedy na problémy, které umíme řešit jen hrubou silou: pak nám je aspoň vhod, že se nenadřeme při programování.

Ve zvoleném programovacím jazyce napište funkci, která navrací, zda je její parametr prvočíslo.

Vizte písemku.