Obsah
1. Nial Array Language: další z jazyků inspirovaných APL
2. Základní vlastnosti programovacího jazyka Nial
3. Stručné porovnání s dalšími jazyky z rodiny APL
4. Překlad a první spuštění interpretru jazyka Nial
5. Pole ve funkci základního datového typu programovacího jazyka Nial
6. Modifikace prvků pole a další základní operace s poli
8. Změna tvaru pole funkcí reshape
9. Funkce umožňující konstrukce polí
10. Funkce pro vygenerování polí
12. Funkce operující s celým polem
13. Pole jakožto rekurzivní datová struktura
15. Zobecněný skalární součin (inner product)
19. Předchozí články o rozsáhlém světu „array programmingu“
1. Nial Array Language: další z jazyků inspirovaných APL
V pořadí již desátém článku věnovaném programovacím jazykům z oblasti „array programmingu“ (viz též odkazy uvedené v devatenácté kapitole) se budeme věnovat programovacímu jazyku, který se jmenuje Nial neboli Nested Interactive Array Language. Tento programovací jazyk patří do rodiny jazyků, které jsou odvozeny od APL, jehož autorem je, jak již víme, Ken Iverson. Do této rodiny patří kromě samotného jazyka APL i jazyky J, K, Q a v neposlední řadě i relativní novinka – jazyk BQN (ovšem patří sem i „kalkulačka“ Ivy). Naproti tomu se v případě programovacího jazyka Nial, kterému se budeme věnovat dnes, o žádnou žhavou novinku nejedná, protože tento programovací jazyk začal vznikat již na začátku osmdesátých let minulého století. I přesto však v něm nalezneme některé zajímavé koncepty, díky nimž se Nial odlišuje od všech výše uvedených jazyků a tedy má smysl se jím zabývat.
2. Základní vlastnosti programovacího jazyka Nial
Jak jsme si již naznačili v úvodní kapitole, je Nial programovacím jazykem pocházejícím z rodiny APL. Do samotného jazyka však byly přidány některé funkcionální prvky, podobně, jako tomu je například v jazyku K či BQN. Základním a ústředním datovým typem je zde (což asi není velké překvapení) n-dimenzionální pole (array), které dokonce při provádění výpočtů nahrazuje i skalární hodnoty. To například znamená, že i znaky, pravdivostní hodnoty nebo celá čísla jsou při provádění různých operací chápána jako pole s jediným prvkem, ovšem jejich typ je odlišný, protože se jedná o takzvané atomy. A logicky je tomu i naopak – pole mohou jako své prvky obsahovat jiná pole, tj. jedná se o rekurzivní datovou strukturu (tento koncept chápání polí ovšem nenajdeme ve všech jazycích odvozených od APL, například ji nemá jazyk J).
Ovšem stejně jako v APL se i v Nialu pracuje s funkcemi jako s operátory, tj. operandy/parametry se mohou zapsat okolo jména funkce (což vyžaduje, aby funkce byly monadické nebo dyadické). Uveďme si jednoduchý příklad:
1 + 2 3
Výše uvedený zápis znamená volání funkce nazvané + alias sum, které se předávají dva parametry – každý z parametrů je přitom chápán jako pole s jediným prvkem, tj. první pole obsahuje prvek s hodnotou 1 a druhé pole obsahuje prvek s hodnotou 2. Hodnota 3 vypsaná na dalším řádku je výsledek celé operace. Opět se z pohledu dalšího zpracování nemusí jednat jen o skalární hodnotu 3, ale o pole s jediným prvkem rovným trojce.
Alternativně lze ovšem funkci volat i tak, že se její jméno uvede na začátku výrazu, za nímž následují parametry funkce:
+ 1 2 3
Takto volaná funkce akceptuje i větší množství parametrů:
+ 1 2 3 6
Namísto symbolu + ovšem můžeme použít i plné jméno funkce sum a přepsat všechny tři předchozí výrazy následovně:
1 sum 2 3 sum 1 2 3 sum 1 2 3 6
Sčítat je ovšem možné i dvě pole, resp. v tomto případě dvojici dvouprvkových vektorů:
1 2 + 2 3 3 5
Podporováno je i přičtení (zdánlivé) skalární hodnoty s polem:
1 + 2 3 4 3 4 5 1 2 3 + 4 5 6 7
Pozor si musíme dát především na to, že se nerozlišují priority aritmetických operací (protože se vlastně jedná o volání funkcí) a operace se vyhodnocují zleva doprava, na rozdíl od většiny ostatních jazyků z rodiny APL. V případě potřeby se tedy musíme pomoci závorkami:
1 + 2 * 3 9 1 + (2 * 3) 7 (1 + 2) * 3 9
3. Stručné porovnání s dalšími jazyky z rodiny APL
Jazyk Nial sice vychází z konceptů, které byly zavedeny v rámci programovacího jazyka APL, ovšem v některých ohledech se od těchto jazyků odlišuje. Především je zde patrná snaha o pojmenování funkcí a operátorů takovým způsobem, aby byl výsledek čitelný. To je poměrně velký posun od filozofie APL, J i K (Q), kde je čitelnost nahrazena za krátký zápis výpočtů či celých algoritmů (což značí, že se jedná o odlišný způsob nasazení těchto jazyků – APL evidentně sází na rozpoznávání vzorů, které se tak postupně stanou součástí „slovníku“ programátora). To je ovšem především syntaktický rozdíl, který nemusí být až tak zásadní. Důležitější jsou další rozdíly, z nichž některé jsou zmíněny na stránce https://github.com/codereport/array-language-comparisons.
Zajímavé je, že funkce (monadické i dyadické) se vyhodnocují zleva doprava, zatímco u dalších APL jazyků je to zprava doleva. Prvky pole jsou indexovány od nuly, zatímco v APL je index prvního prvku volitelný a běžné „inženýrské“ a matematické/statistické jazyky indexují od jedničky (Fortran, Julia, Mathematica, Matlab, R, Wolfram language).
4. Překlad a první spuštění interpretru jazyka Nial
Programovací jazyk Nial je dostupný jak ve formě binárních spustitelných souborů, tak i ve formě zdrojových kódů. Ukažme si tedy překlad Nialu. K tomu budeme potřebovat překladač programovacího jazyka C, překladač jazyka C++ (kvůli naprosto marginální části kódu), a taktéž CMake.
Nejprve naklonujeme repositář se zdrojovými kódy:
$ git clone https://github.com/niallang/Nial_Development.git Cloning into 'Nial_Development'... remote: Enumerating objects: 2024, done. remote: Counting objects: 100% (205/205), done. remote: Compressing objects: 100% (140/140), done. remote: Total 2024 (delta 83), reused 144 (delta 57), pack-reused 1819 Receiving objects: 100% (2024/2024), 31.04 MiB | 36.83 MiB/s, done. Resolving deltas: 100% (549/549), done.
Ve druhém kroku se přesuneme do naklonovaného repositáře a spustíme překlad:
$ bash ./build.sh -- The C compiler identification is GNU 12.2.1 -- The CXX compiler identification is GNU 12.2.1 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /root/Nial_Development/BuildCore/build [ 3%] Building C object CMakeFiles/nialcore.dir/absmach.c.o [ 7%] Building C object CMakeFiles/nialcore.dir/arith.c.o [ 10%] Building C object CMakeFiles/nialcore.dir/atops.c.o [ 14%] Building C object CMakeFiles/nialcore.dir/basics.c.o [ 17%] Building C object CMakeFiles/nialcore.dir/blders.c.o [ 21%] Building C object CMakeFiles/nialcore.dir/compare.c.o [ 25%] Building C object CMakeFiles/nialcore.dir/eval.c.o [ 28%] Building C object CMakeFiles/nialcore.dir/insel.c.o [ 32%] Building C object CMakeFiles/nialcore.dir/lib_main.c.o [ 35%] Building C object CMakeFiles/nialcore.dir/linalg.c.o [ 39%] Building C object CMakeFiles/nialcore.dir/logicops.c.o [ 42%] Building C object CMakeFiles/nialcore.dir/main_stu.c.o [ 46%] Building C object CMakeFiles/nialcore.dir/linenoise.c.o [ 50%] Building C object CMakeFiles/nialcore.dir/parse.c.o [ 53%] Building C object CMakeFiles/nialcore.dir/picture.c.o [ 57%] Building C object CMakeFiles/nialcore.dir/profile.c.o [ 60%] Building C object CMakeFiles/nialcore.dir/scan.c.o [ 64%] Building C object CMakeFiles/nialcore.dir/symtab.c.o [ 67%] Building C object CMakeFiles/nialcore.dir/systemops.c.o [ 71%] Building C object CMakeFiles/nialcore.dir/trig.c.o [ 75%] Building C object CMakeFiles/nialcore.dir/trs.c.o [ 78%] Building C object CMakeFiles/nialcore.dir/unixif.c.o [ 82%] Building C object CMakeFiles/nialcore.dir/windowsif.c.o [ 85%] Building C object CMakeFiles/nialcore.dir/utils.c.o [ 89%] Building C object CMakeFiles/nialcore.dir/wsmanage.c.o [ 92%] Building C object CMakeFiles/nialcore.dir/bitops.c.o [ 96%] Building C object CMakeFiles/nialcore.dir/fileio.c.o [100%] Linking C executable nialcore [100%] Built target nialcore Completed work to generate source code for basic nial: -- The C compiler identification is GNU 12.2.1 -- The CXX compiler identification is GNU 12.2.1 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /root/Nial_Development/BuildNial/build [ 3%] Building C object CMakeFiles/nial.dir/absmach.c.o [ 7%] Building C object CMakeFiles/nial.dir/arith.c.o [ 10%] Building C object CMakeFiles/nial.dir/atops.c.o [ 14%] Building C object CMakeFiles/nial.dir/basics.c.o [ 17%] Building C object CMakeFiles/nial.dir/blders.c.o [ 21%] Building C object CMakeFiles/nial.dir/compare.c.o [ 25%] Building C object CMakeFiles/nial.dir/eval.c.o [ 28%] Building C object CMakeFiles/nial.dir/insel.c.o [ 32%] Building C object CMakeFiles/nial.dir/lib_main.c.o [ 35%] Building C object CMakeFiles/nial.dir/linalg.c.o [ 39%] Building C object CMakeFiles/nial.dir/logicops.c.o [ 42%] Building C object CMakeFiles/nial.dir/main_stu.c.o [ 46%] Building C object CMakeFiles/nial.dir/linenoise.c.o [ 50%] Building C object CMakeFiles/nial.dir/parse.c.o [ 53%] Building C object CMakeFiles/nial.dir/picture.c.o [ 57%] Building C object CMakeFiles/nial.dir/profile.c.o [ 60%] Building C object CMakeFiles/nial.dir/scan.c.o [ 64%] Building C object CMakeFiles/nial.dir/symtab.c.o [ 67%] Building C object CMakeFiles/nial.dir/systemops.c.o [ 71%] Building C object CMakeFiles/nial.dir/trig.c.o [ 75%] Building C object CMakeFiles/nial.dir/trs.c.o [ 78%] Building C object CMakeFiles/nial.dir/unixif.c.o [ 82%] Building C object CMakeFiles/nial.dir/windowsif.c.o [ 85%] Building C object CMakeFiles/nial.dir/utils.c.o [ 89%] Building C object CMakeFiles/nial.dir/wsmanage.c.o [ 92%] Building C object CMakeFiles/nial.dir/bitops.c.o [ 96%] Building C object CMakeFiles/nial.dir/fileio.c.o [100%] Linking C executable nial [100%] Built target nial
Samotné jádro jazyka Nial (bez dalších knihoven) je dostupné v podadresáři BuildCore/build:
$ cd BuildCore/build
Výsledný spustitelný soubor se jmenuje nialcore:
$ ls -l total 584 -rw-r--r--. 1 tester tester 14019 Sep 29 08:46 CMakeCache.txt drwxr-xr-x. 1 tester tester 294 Sep 29 08:46 CMakeFiles -rw-r--r--. 1 tester tester 1644 Sep 29 08:46 cmake_install.cmake -rw-r--r--. 1 tester tester 23109 Sep 29 08:46 Makefile -rwxr-xr-x. 1 tester tester 549280 Sep 29 08:46 nialcore
Můžeme si otestovat jeho spuštění:
$ ./nialcore SYNTAX: nial [(+|-)size Wssize] [-defs Filename] [-i] [-lws WSName] [-h] -size Wssize Begin with a workspace size of Wssize words. A suffix of G, M or K can be used to indicate Giga words, Mega words or Kilo words respectively. The workspace expands if space is available. +size Wssize Fix the workspace size at Wssize words with no expansion. -defs Filename After loading the initial workspace the file Filename.ndf is loaded and executed without displaying input lines. -lws Wsname A previously saved workspace file is loaded on startup. -i Execute in interactive mode with a top level loop. -h Display command line syntax (this text). Examples: nial -i nial -defs app.ndf nial +size 50M -defs newfns
Interaktivní smyčka REPL se spustí po zadání přepínače -i:
$ ./nialcore -i Q'Nial V7.0 Open Source Edition Intel x86 64bit Linux Sep 29 2022 Copyright (c) NIAL Systems Limited clear workspace created
Nyní lze zadat nějaký výraz, který se ihned vyhodnotí:
1+2 3
Pro opuštění REPLu nelze použít klávesovou zkratku Ctrl+D, ale příkaz „Bye“:
Bye
bye
5. Pole ve funkci základního datového typu programovacího jazyka Nial
V programovacím jazyku Nial, ostatně podobně, jako je tomu i u dalších jazyků odvozených od APL, je základním datovým typem pole (array), konkrétně obdélníkové pole, které může (rekurzivně) jako své prvky obsahovat další pole. V Nialu jsou pole obecně nehomogenním datovým typem, což znamená, že prvky jednoho pole mohou být různého typu. Obecně platí, že prvek pole je buď další pole (rekurzivní datová struktura) nebo se jedná o atom. Existuje přitom šest typů atomů: pravdivostní hodnota, celé číslo, reálné číslo, znak, řetězec a tzv. fault reprezentující nějakou formu chyby, například ?noexpr, ?eof, ?O nebo ?I.
Jednorozměrné pole se zapisuje výčtem svých prvků (jako oddělovač slouží bílé znaky):
1 2 3 1 2 3
Aby bylo zřejmé, že se skutečně jedná o pole, změníme způsob jejich výpisu na terminál příkazy set:
set "diagram sketch
Tento příkaz zajistí, že se vykreslí vždy celá interní struktura pole, včetně vnořených polí.
Další volbou je:
set "decor "nodecor
Touto volbou se určuje, jakým způsobem se zobrazí znaky, řetězce a hodnoty fault tak, aby bylo zřejmé, o jaké hodnoty/struktury se jedná.
Nyní znovu zapíšeme výraz s jednorozměrným polem:
1 2 3 +-+-+-+ |1|2|3| +-+-+-+
Pole lze ovšem zkonstruovat i s využitím různých funkcí, například funkce count (což zhruba odpovídá iotě z APL):
count 12 +-+-+-+-+-+-+-+-+-+--+--+--+ |1|2|3|4|5|6|7|8|9|10|11|12| +-+-+-+-+-+-+-+-+-+--+--+--+
Poněkud speciální formou pole je prázdné pole, tj. pole bez prvků. To je reprezentováno symbolem null:
null + | +
6. Modifikace prvků pole a další základní operace s poli
Prvky pole je možné změnit (modifikovat, mutovat) operací nazvanou place. Tuto operaci si otestujeme na poli s deseti prvky:
x is count 10
Změna prvního prvku pole na hodnotu 42 vypadá následovně:
42 0 place x 42 2 3 4 5 6 7 8 9 10
Můžeme ovšem vložit do stejného prvku i kopii původního pole x, přičemž výsledkem bude složitější datová struktura:
x 0 place x +----------------------+-+-+-+-+-+-+-+-+--+ |+-+-+-+-+-+-+-+-+-+--+|2|3|4|5|6|7|8|9|10| ||1|2|3|4|5|6|7|8|9|10|| | | | | | | | | | |+-+-+-+-+-+-+-+-+-+--+| | | | | | | | | | +----------------------+-+-+-+-+-+-+-+-+--+
Další užitečnou operací je zjištění maximálního a minimálního prvku v poli:
x is count 10 max x 10 min x 1
Tyto funkce ovšem dokážou pracovat i se dvěma poli nebo se skalárem a polem:
5 max x +-+-+-+-+-+-+-+-+-+--+ |5|5|5|5|5|6|7|8|9|10| +-+-+-+-+-+-+-+-+-+--+ 5 min x +-+-+-+-+-+-+-+-+-+-+ |1|2|3|4|5|5|5|5|5|5| +-+-+-+-+-+-+-+-+-+-+
Výpočet součtu či součinu všech prvků ve vektoru nebo matici:
x is count 10 sum x 55 product x 3628800
Dále můžeme aplikovat nějakou operaci na celou matici:
x is 5 5 reshape count 25 x mod 2 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
7. Počet dimenzí a tvar pole
Interně je pole uloženo v jediném bloku paměti, ke kterému jsou přidány další metainformace. Především se jedná o počet dimenzí pole (v terminologii jazyka Nial se používá označení valence) a tvar pole neboli shape. Samotný tvar pole je reprezentován jako vektor délek rozsahů jednotlivých dimenzí pole, což například znamená, že pro matici se třemi řádky a čtyřmi sloupci bude tvar (shape) reprezentován vektorem 3, 4 (délka vektoru = počet jeho prvků, odpovídá počtu dimenzí pole.
Pole s počtem dimenzí 0 až 2 mají speciální označení a setkáme se s nimi jak v matematice, tak i v informatice:
Dimenzí | Běžné označeni |
---|---|
0 | single, atom, „jednice“? |
1 | seznam, vektor |
2 | tabulka, matice |
2 a více | n-rozměrné pole/matice |
Počet dimenzí lze získat funkcí valence:
valence null 1 valence 42 0 valence 1 2 3 1
Dvourozměrné pole získáme funkcí reshape popsané dále. Zde nejdříve uložíme pole do proměnné x a následně získáme počet jeho dimenzí:
x is 3 4 reshape 0 x +-+-+-+-+ |0|0|0|0| +-+-+-+-+ |0|0|0|0| +-+-+-+-+ |0|0|0|0| +-+-+-+-+ valence x 2
Podobně pro pole trojrozměrné:
y is 2 2 2 reshape 0 y +-+-+ +-+-+ |0|0| |0|0| +-+-+ +-+-+ |0|0| |0|0| +-+-+ +-+-+ valence y 3
Tvar pole (shape) se získá funkcí shape, přičemž pro atomy se bude vracet prázdné pole:
shape null +-+ |0| +-+ shape 42 + | + shape 1 2 +-+ |2| +-+ shape 1 2 3 4 +-+ |4| +-+ shape [] +-+ |0| +-+
Dvourozměrné a trojrozměrné pole:
x is 3 4 reshape count 12 shape x +-+-+ |3|4| +-+-+ x is 3 4 2 reshape count 24 shape x +-+-+-+ |3|4|2| +-+-+-+
Existují ještě další dvě užitečné funkce, které se dotazují na metainformace o polích. Tyto funkce se jmenují tally (počet prvků) a axes (informace o osách, resp. „indexy“ os nebo dimenzí):
tally null 0 tally 42 1 tally 1 2 3 3 x is 3 4 reshape 0 tally x 12
a:
axes null 0 axes 42 (prázdná hodnota) axes 1 2 3 0 axes x 0 1
8. Změna tvaru pole funkcí reshape
Další velmi důležitou funkcí, s níž se v praxi poměrně často setkáme (například i v NumPy, které z „array jazyků“ vychází), je funkce nazvaná reshape, která dokáže změnit velikost matice a vhodným způsobem přeorganizovat prvky v původní matici (celý koncept je převzat z původního APL, ostatně jak jinak). Této funkci se předávají dva parametry. Prvním parametrem je vektor s prvky určujícími tvar výsledného pole a druhým parametrem je vstupní pole (vektor, matice, …).
V následujícím příkladu je ukázáno, jak se z původního šestiprvkového vektoru vytvoří matice se třemi sloupci a dvěma řádky:
2 3 reshape 1 2 3 4 5 6 +-+-+-+ |1|2|3| +-+-+-+ |4|5|6| +-+-+-+
Víme již, že funkcí count můžeme vytvořit vektor s číselnou posloupností:
count 12 +-+-+-+-+-+-+-+-+-+--+--+--+ |1|2|3|4|5|6|7|8|9|10|11|12| +-+-+-+-+-+-+-+-+-+--+--+--+
Toho můžeme využít pro tvorbu 2D matic:
4 3 reshape count 12 +--+--+--+ | 1| 2| 3| +--+--+--+ | 4| 5| 6| +--+--+--+ | 7| 8| 9| +--+--+--+ |10|11|12| +--+--+--+
Trojrozměrná datová struktura, kterou si můžeme představit jako dvě matice umístěné nad sebe:
2 3 4 reshape count 12 +-+--+--+--+ +-+--+--+--+ |1| 2| 3| 4| |1| 2| 3| 4| +-+--+--+--+ +-+--+--+--+ |5| 6| 7| 8| |5| 6| 7| 8| +-+--+--+--+ +-+--+--+--+ |9|10|11|12| |9|10|11|12| +-+--+--+--+ +-+--+--+--+
Pokud je na pravé straně reshape nedostatečný počet prvků pro vyplnění nové matice, budou prvky opakovány:
5 5 reshape 42 +--+--+--+--+--+ |42|42|42|42|42| +--+--+--+--+--+ |42|42|42|42|42| +--+--+--+--+--+ |42|42|42|42|42| +--+--+--+--+--+ |42|42|42|42|42| +--+--+--+--+--+ |42|42|42|42|42| +--+--+--+--+--+
Dtto, ovšem pro vstupní vektor s pouhými dvěma prvky:
9 9 reshape 1 0 +-+-+-+-+-+-+-+-+-+ |1|0|1|0|1|0|1|0|1| +-+-+-+-+-+-+-+-+-+ |0|1|0|1|0|1|0|1|0| +-+-+-+-+-+-+-+-+-+ |1|0|1|0|1|0|1|0|1| +-+-+-+-+-+-+-+-+-+ |0|1|0|1|0|1|0|1|0| +-+-+-+-+-+-+-+-+-+ |1|0|1|0|1|0|1|0|1| +-+-+-+-+-+-+-+-+-+ |0|1|0|1|0|1|0|1|0| +-+-+-+-+-+-+-+-+-+ |1|0|1|0|1|0|1|0|1| +-+-+-+-+-+-+-+-+-+ |0|1|0|1|0|1|0|1|0| +-+-+-+-+-+-+-+-+-+ |1|0|1|0|1|0|1|0|1| +-+-+-+-+-+-+-+-+-+
Použít lze i další datové typy, nikoli pouze celočíselné prvky:
9 9 reshape " "X +--+--+--+--+--+--+--+--+--+ |" |"X|" |"X|" |"X|" |"X|" | +--+--+--+--+--+--+--+--+--+ |"X|" |"X|" |"X|" |"X|" |"X| +--+--+--+--+--+--+--+--+--+ |" |"X|" |"X|" |"X|" |"X|" | +--+--+--+--+--+--+--+--+--+ |"X|" |"X|" |"X|" |"X|" |"X| +--+--+--+--+--+--+--+--+--+ |" |"X|" |"X|" |"X|" |"X|" | +--+--+--+--+--+--+--+--+--+ |"X|" |"X|" |"X|" |"X|" |"X| +--+--+--+--+--+--+--+--+--+ |" |"X|" |"X|" |"X|" |"X|" | +--+--+--+--+--+--+--+--+--+ |"X|" |"X|" |"X|" |"X|" |"X| +--+--+--+--+--+--+--+--+--+ |" |"X|" |"X|" |"X|" |"X|" | +--+--+--+--+--+--+--+--+--+
9. Funkce umožňující konstrukce polí
V programovacím jazyku Nial existuje několik funkcí, které umožňují konstrukci pole, typicky ze zadaných prvků (nebo jediného prvku), popř. na základě určitého algoritmu. Základní funkce zkonstruují pole z jediného prvku, dvojice prvků, popř. ze seznamu prvků a dalšího prvku (tedy připojením dalšího prvku). Jedná se o následující funkce:
# pole s jediným prvkem solitary 42 +--+ |42| +--+
Konstrukce pole s pouhými dvěma prvky – páru:
# pár neboli pole se dvěma prvky 1 pair 2 +-+-+ |1|2| +-+-+ # pár, kterému se předají složitější vstupy 1 pair 2 3 4 +-+-------+ |1|+-+-+-+| | ||2|3|4|| | |+-+-+-+| +-+-------+ # pár, kterému se předají složitější vstupy 1 2 3 pair 4 +-------+-+ |+-+-+-+|4| ||1|2|3|| | |+-+-+-+| | +-------+-+
Další funkce se jmenuje hitch. Tato funkce pracuje jinak, protože na své pravé straně (druhý operand) očekává větší množství prvků:
1 hitch 2 +-+-+ |1|2| +-+-+ 1 hitch 2 3 4 +-+-+-+-+ |1|2|3|4| +-+-+-+-+ 1 2 3 hitch 4 +-------+-+ |+-+-+-+|4| ||1|2|3|| | |+-+-+-+| | +-------+-+
A funkce s opačným významem se jmenuje append. Tato funkce přidává prvek na konec seznamu a vrací pole:
1 append 2 +-+-+ |1|2| +-+-+ 1 append 2 3 4 +-+-------+ |1|+-+-+-+| | ||2|3|4|| | |+-+-+-+| +-+-------+ 1 2 3 append 4 +-+-+-+-+ |1|2|3|4| +-+-+-+-+
10. Funkce pro vygenerování polí
Další sada funkcí slouží pro vygenerování celého pole na základě zvoleného algoritmu.
Vytvoření jednorozměrného pole se sekvencí hodnot začínajících buď od nuly (tell) nebo od jedničky (count):
tell 10 +-+-+-+-+-+-+-+-+-+-+ |0|1|2|3|4|5|6|7|8|9| +-+-+-+-+-+-+-+-+-+-+ count 10 +-+-+-+-+-+-+-+-+-+--+ |1|2|3|4|5|6|7|8|9|10| +-+-+-+-+-+-+-+-+-+--+
V případě, že budeme chtít odlišnou sekvenci, můžeme použít výpočty s poli:
1 + count 10 +-+-+-+-+-+-+-+-+--+--+ |2|3|4|5|6|7|8|9|10|11| +-+-+-+-+-+-+-+-+--+--+ count 10 + count 10 +-+-+-+-+--+--+--+--+--+--+ |2|4|6|8|10|12|14|16|18|20| +-+-+-+-+--+--+--+--+--+--+
Konstrukce dvourozměrného pole kombinací reshape a count/tell:
3 4 reshape count 12 +-+--+--+--+ |1| 2| 3| 4| +-+--+--+--+ |5| 6| 7| 8| +-+--+--+--+ |9|10|11|12| +-+--+--+--+ 3 4 reshape tell 12 +-+-+--+--+ |0|1| 2| 3| +-+-+--+--+ |4|5| 6| 7| +-+-+--+--+ |8|9|10|11| +-+-+--+--+
Další možnosti:
3 4 reshape count 12 + 100 +---+---+---+---+ |101|102|103|104| +---+---+---+---+ |105|106|107|108| +---+---+---+---+ |109|110|111|112| +---+---+---+---+
Získat je možné i pole s indexy (adresami) prvků původního pole:
grid 1 2 +-+-+ |0|1| +-+-+ grid 1 2 3 +-+-+-+ |0|1|2| +-+-+-+ grid 3 4 2 1 +-+-+-+-+ |0|1|2|3| +-+-+-+-+ grid (3 4 reshape 12) +-----+-----+-----+-----+ |+-+-+|+-+-+|+-+-+|+-+-+| ||0|0|||0|1|||0|2|||0|3|| |+-+-+|+-+-+|+-+-+|+-+-+| +-----+-----+-----+-----+ |+-+-+|+-+-+|+-+-+|+-+-+| ||1|0|||1|1|||1|2|||1|3|| |+-+-+|+-+-+|+-+-+|+-+-+| +-----+-----+-----+-----+ |+-+-+|+-+-+|+-+-+|+-+-+| ||2|0|||2|1|||2|2|||2|3|| |+-+-+|+-+-+|+-+-+|+-+-+| +-----+-----+-----+-----+
A konečně si ukažme, jak lze vytvořit pole s pseudonáhodnými hodnotami:
random 10 0.726391 0.448169 0.384064 0.961273 0.123186 0.384953 0.911016 0.44919 0.536883 0.385413
Změna rozsahu pseudonáhodných hodnot:
10 * random 20 0.124268 8.57941 4.22553 8.50044 6.85217 4.47933 4.07353 3.74976 2.13688 4.55871 8.20644 5.64311 3.67626 6.82072 5.87837 7.69379 9.57127 4.40364 1.92131 1.42347
Vygenerování náhodných hodnot od 0 do 9:
floor(10 * random 20) 4 8 4 4 6 7 7 6 8 2 4 1 0 3 9 7 3 8 8 7
Dosazení pole do proměnné:
x is floor(10 * random 20) x 8 6 2 1 0 0 5 6 5 4 2 6 5 3 1 6 5 4 5 3
Dtto, ale pro dvourozměrné pole:
random 5 5 +----------+--------+--------+--------+--------+ | 0.123186|0.384953|0.911016| 0.44919|0.536883| +----------+--------+--------+--------+--------+ | 0.385413|0.639681|0.119586|0.882235| 0.72909| +----------+--------+--------+--------+--------+ | 0.810901|0.819432|0.193461|0.498833|0.880408| +----------+--------+--------+--------+--------+ |0.00925989|0.631015|0.476912|0.455139| 0.52156| +----------+--------+--------+--------+--------+ | 0.851008|0.893033|0.210305|0.603614|0.940779| +----------+--------+--------+--------+--------+
popř.:
floor(10*random 10 10) +-+-+-+-+-+-+-+-+-+-+ |8|2|6|9|6|2|6|7|5|6| +-+-+-+-+-+-+-+-+-+-+ |2|6|0|6|1|9|7|1|1|6| +-+-+-+-+-+-+-+-+-+-+ |3|8|5|8|1|7|7|6|0|7| +-+-+-+-+-+-+-+-+-+-+ |2|9|5|2|4|8|2|2|3|7| +-+-+-+-+-+-+-+-+-+-+ |7|9|2|3|0|3|7|8|1|2| +-+-+-+-+-+-+-+-+-+-+ |6|8|3|6|9|1|8|3|3|1| +-+-+-+-+-+-+-+-+-+-+ |5|0|0|6|8|9|3|2|5|8| +-+-+-+-+-+-+-+-+-+-+ |5|7|4|4|8|4|1|6|8|5| +-+-+-+-+-+-+-+-+-+-+ |4|0|0|6|3|2|9|4|7|2| +-+-+-+-+-+-+-+-+-+-+ |2|9|8|9|3|0|8|4|8|6| +-+-+-+-+-+-+-+-+-+-+
11. Pole a relační operátory
Jazyk Nial umožňuje porovnání všech prvků pole s nějakou zadanou hodnotou. Výsledkem je potom nové pole, jehož prvky jsou pravdivostní hodnoty, jenž jsou ovšem v Nialu reprezentovány znaky l (true) a o (false). To je netradiční reprezentace pravdivostních hodnot, na druhou stranu je však jisté, že tyto hodnoty budou uloženy v jediném bajtu a nikoli například jako celé 32bitové číslo:
1=1 l 1=2 o
Nejprve vytvoříme pole (zde vektor), který budeme testovat:
x is count 10 x +-+-+-+-+-+-+-+-+-+--+ |1|2|3|4|5|6|7|8|9|10| +-+-+-+-+-+-+-+-+-+--+
Porovnání všech prvků se zadanou hodnotou:
x <= 5 +-+-+-+-+-+-+-+-+-+-+ |l|l|l|l|l|o|o|o|o|o| +-+-+-+-+-+-+-+-+-+-+ x >= 5 +-+-+-+-+-+-+-+-+-+-+ |o|o|o|o|l|l|l|l|l|l| +-+-+-+-+-+-+-+-+-+-+ 5 < x +-+-+-+-+-+-+-+-+-+-+ |o|o|o|o|o|l|l|l|l|l| +-+-+-+-+-+-+-+-+-+-+
Stejnou operaci je možné provést i s dvourozměrným polem:
x is 5 5 reshape count 25 x 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 x <= 12 lllll lllll llooo ooooo ooooo
x is count 10 y is count 10 x = y l x ~= y o
A pro nepatrně odlišná pole, která se od sebe odlišují jediným prvkem:
x is count 10 y is 1 2 3 4 -5 6 7 8 9 x +-+-+-+-+-+-+-+-+-+--+ |1|2|3|4|5|6|7|8|9|10| +-+-+-+-+-+-+-+-+-+--+ y +-+-+-+-+--+-+-+-+-+ |1|2|3|4|-5|6|7|8|9| +-+-+-+-+--+-+-+-+-+ x = y o x ~= y l
12. Funkce operující s celým polem
Některé funkce, které nalezneme ve standardní knihovně jazyka Nial, operují s celým polem, resp. přesněji řečeno se u většiny těchto funkcí předpokládá, že se bude jednat o vektory nebo matice. Dále popsané funkce budeme testovat s následujícím polem (konkrétně s dvourozměrnou maticí):
x is 2 3 reshape count 6 x +-+-+-+ |1|2|3| +-+-+-+ |4|5|6| +-+-+-+
Transpozice matice je realizována funkcí transpose:
transpose x +-+-+ |1|4| +-+-+ |2|5| +-+-+ |3|6| +-+-+
Rotace prvků doprava (první operand je záporný) nebo doleva (první operand je kladný). Povšimněte si, že prvky jsou v poli posouvány nejenom v rámci sloupců, ale překračují i řádky:
-1 rotate x +-+-+-+ |6|1|2| +-+-+-+ |3|4|5| +-+-+-+ -2 rotate x +-+-+-+ |5|6|1| +-+-+-+ |2|3|4| +-+-+-+ -3 rotate x +-+-+-+ |4|5|6| +-+-+-+ |1|2|3| +-+-+-+ 1 rotate x +-+-+-+ |2|3|4| +-+-+-+ |5|6|1| +-+-+-+
Otočení všech prvků ve vektoru nebo matici:
reverse x +-+-+-+ |6|5|4| +-+-+-+ |3|2|1| +-+-+-+
Tato operace je zvláště výhodná u vektorů:
reverse count 10 +--+-+-+-+-+-+-+-+-+-+ |10|9|8|7|6|5|4|3|2|1| +--+-+-+-+-+-+-+-+-+-+
13. Pole jakožto rekurzivní datová struktura
Vzhledem k tomu, že pole mohou jako své prvky obsahovat další pole, je možné v programovacím jazyce Nial tvořit i dosti složité datové struktury. Podívejme se například na vytvoření pole, v němž každý prvek obsahuje další pole, konkrétně dvojice celočíselných prvků:
count 10 + [1 2] +-----+-----+-----+-----+-----+-----+-----+------+-------+-------+ |+-+-+|+-+-+|+-+-+|+-+-+|+-+-+|+-+-+|+-+-+|+-+--+|+--+--+|+--+--+| ||2|3|||3|4|||4|5|||5|6|||6|7|||7|8|||8|9|||9|10|||10|11|||11|12|| |+-+-+|+-+-+|+-+-+|+-+-+|+-+-+|+-+-+|+-+-+|+-+--+|+--+--+|+--+--+| +-----+-----+-----+-----+-----+-----+-----+------+-------+-------+
Podobným způsobem lze realizovat i složitější matice, jejichž prvky jsou pole:
3 4 reshape count 12 + [10 10 10 10] +-------------+-------------+-------------+-------------+ |+--+--+--+--+|+--+--+--+--+|+--+--+--+--+|+--+--+--+--+| ||11|11|11|11|||12|12|12|12|||13|13|13|13|||14|14|14|14|| |+--+--+--+--+|+--+--+--+--+|+--+--+--+--+|+--+--+--+--+| +-------------+-------------+-------------+-------------+ |+--+--+--+--+|+--+--+--+--+|+--+--+--+--+|+--+--+--+--+| ||15|15|15|15|||16|16|16|16|||17|17|17|17|||18|18|18|18|| |+--+--+--+--+|+--+--+--+--+|+--+--+--+--+|+--+--+--+--+| +-------------+-------------+-------------+-------------+ |+--+--+--+--+|+--+--+--+--+|+--+--+--+--+|+--+--+--+--+| ||19|19|19|19|||20|20|20|20|||21|21|21|21|||22|22|22|22|| |+--+--+--+--+|+--+--+--+--+|+--+--+--+--+|+--+--+--+--+| +-------------+-------------+-------------+-------------+
Pro zápis složitějších struktur můžeme použít i notaci, které silně připomíná LISPovské jazyky. Povšimněte si, jak zápis se závorkami přesně odpovídá výsledné datové struktuře:
(1) 1 (1 2) +-+-+ |1|2| +-+-+ (1 (2 3)) +-+-----+ |1|+-+-+| | ||2|3|| | |+-+-+| +-+-----+ (1 (2 (3 4 5 6))) +-+-------------+ |1|+-+---------+| | ||2|+-+-+-+-+|| | || ||3|4|5|6||| | || |+-+-+-+-+|| | |+-+---------+| +-+-------------+ (1 (2 (3 4 5 6) 7) 8) +-+---------------+-+ |1|+-+---------+-+|8| | ||2|+-+-+-+-+|7|| | | || ||3|4|5|6|| || | | || |+-+-+-+-+| || | | |+-+---------+-+| | +-+---------------+-+ (1 2 (3 4 5 6) 7 8) +-+-+---------+-+-+ |1|2|+-+-+-+-+|7|8| | | ||3|4|5|6|| | | | | |+-+-+-+-+| | | +-+-+---------+-+-+ (1 2 (3 4) (5 6) 7 8) +-+-+-----+-----+-+-+ |1|2|+-+-+|+-+-+|7|8| | | ||3|4|||5|6|| | | | | |+-+-+|+-+-+| | | +-+-+-----+-----+-+-+
Přičtení hodnoty 100 ke všem prvkům pole je vlastně rekurzivní operací, protože například přičtení ke třetímu prvku znamená operaci (103 104) + 100 atd.:
(1 2 (3 4) (5 6) 7 8) + 100 +---+---+---------+---------+---+---+ |101|102|+---+---+|+---+---+|107|108| | | ||103|104|||105|106|| | | | | |+---+---+|+---+---+| | | +---+---+---------+---------+---+---+
Totéž platí i pro řetězce:
1 'abc' 'def' +-+-------+-------+ |1|+-+-+-+|+-+-+-+| | ||a|b|c|||d|e|f|| | |+-+-+-+|+-+-+-+| +-+-------+-------+
Alternativní způsoby zápisu:
[1 [2 3] 4] +-----------+ |+-+-----+-+| ||1|+---+|4|| || ||2 3|| || || |+---+| || |+-+-----+-+| +-----------+ [1 [2 3] 4] + count 4 +-----------+-----------+-----------+-----------+ |+-+-----+-+|+-+-----+-+|+-+-----+-+|+-+-----+-+| ||2|+---+|5|||3|+---+|6|||4|+---+|7|||5|+---+|8|| || ||3 4|| ||| ||4 5|| ||| ||5 6|| ||| ||6 7|| || || |+---+| ||| |+---+| ||| |+---+| ||| |+---+| || |+-+-----+-+|+-+-----+-+|+-+-----+-+|+-+-----+-+| +-----------+-----------+-----------+-----------+ 2 2 reshape ([1 [2 3] 4] + count 4) +-----------+-----------+ |+-+-----+-+|+-+-----+-+| ||2|+---+|5|||3|+---+|6|| || ||3 4|| ||| ||4 5|| || || |+---+| ||| |+---+| || |+-+-----+-+|+-+-----+-+| +-----------+-----------+ |+-+-----+-+|+-+-----+-+| ||4|+---+|7|||5|+---+|8|| || ||5 6|| ||| ||6 7|| || || |+---+| ||| |+---+| || |+-+-----+-+|+-+-----+-+| +-----------+-----------+
14. Zobecněný outer product
S využitím operátoru outer product, s nímž jsme se již setkali při popisu jazyka APL a jenž umožňuje z dvojice vektorů vytvořit matici (a jedná se o jednu z jeho nejlepších vlastností) je možné zkonstruovat velké množství matic se speciálními vlastnostmi; tyto matice mohou mít samozřejmě téměř libovolnou velikost. Jedná se například o jednotkové matice (obsahují jedničky v diagonále, ostatní prvky jsou nulové), trojúhelníkové matice různého typu (jedničky se nachází pod či nad diagonálou, ostatní prvky jsou nulové) atd. Tvorba těchto matic je ilustrována na následujících příkladech, ve kterých se často používají porovnávací (relační) funkce. Povšimněte si, jakým způsobem se tyto funkce musí zapsat:
# vektor s prvky 1 až 5 x is count 5 # malá násobilka x outer * x 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25 # první pokus o vytvoření jednotkové matice x outer = x loooo olooo ooloo ooolo ooool # druhý pokus o vytvoření jednotkové matice 1 * (x outer = x) 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 # trojúhelníková matice 1 * (x outer <= x) 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 # odlišná trojúhelníková matice 1 * (x outer >= x) 1 0 0 0 0 1 1 0 0 0 1 1 1 0 0 1 1 1 1 0 1 1 1 1 1
Použít samozřejmě můžeme dva odlišné vstupní vektory:
x is count 10 y is count 5 x outer * y 1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25 6 12 18 24 30 7 14 21 28 35 8 16 24 32 40 9 18 27 36 45 10 20 30 40 50 y outer * x 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50
15. Zobecněný skalární součin (inner product)
Programovací jazyk Nial, ostatně jako většina ostatních jazyků odvozených od APL, podporuje i výpočet zobecněného skalárního součinu. Připomeňme si, že klasický skalární součin spočívá v tom, že se vynásobí odpovídající prvky dvou vektorů (tedy první prvek z prvního vektoru s prvním prvkem druhého vektoru atd.) a výsledná sekvence hodnot se sečte. Zobecnění spočívá v tom, že jak násobení, tak i výsledný součet je zcela volitelnou operací, což má dalekosáhlé důsledky (ostatně jak zobecněný skalární součin, tak i zobecněný vnější součin jsou velmi silnými zbraněmi „APL jazyků“). Podívejme se nyní, jak je skalární součin zapisován v Nialu, zejména jak se specifikují obě operace:
Klasický skalární součin:
x is count 10 x inner [*,+] x 385
Otočení pořadí obou operací (odpovídající prvky jsou sečteny, výsledky vynásobeny):
x inner [*,+] x 3715891200
Výpočet, kolik prvků ve dvou vektorech si odpovídá (lze využít pro vyhledávání řetězců atd.):
1 2 3 4 inner [+,=] 1 9 8 4 2
Test na úplnou rovnost prvků dvou vektorů:
1 2 3 4 inner [and,=] 1 1 1 1 o 1 2 3 4 inner [and,=] 1 2 3 4 l
Ovšem vstupem nemusí být jen vektory, ale i matice. Například takto lze nahradit operaci maticového součinu:
t1 is 3 2 reshape count 6 t2 is 2 4 reshape count 8 t1 1 2 3 4 5 6 t2 1 2 3 4 5 6 7 8 t1 inner [+,*] t2 11 14 17 20 23 30 37 44 35 46 57 68
16. Další ukázky práce s poli
V této kapitole jsou uvedeny některé ukázky práce s poli, které se tematicky nehodily do předchozích kapitol.
Konstrukce nulové matice a získání tvaru této matice:
x is 3 4 reshape 0 x +-+-+-+-+ |0|0|0|0| +-+-+-+-+ |0|0|0|0| +-+-+-+-+ |0|0|0|0| +-+-+-+-+ shape x +-+-+ |3|4| +-+-+
Vytvoření trojrozměrného pole (povšimněte si způsobu jeho zobrazení):
x is 4 3 2 reshape count 24 x +-+-+ +--+--+ +--+--+ +--+--+ |1|2| | 7| 8| |13|14| |19|20| +-+-+ +--+--+ +--+--+ +--+--+ |3|4| | 9|10| |15|16| |21|22| +-+-+ +--+--+ +--+--+ +--+--+ |5|6| |11|12| |17|18| |23|24| +-+-+ +--+--+ +--+--+ +--+--+ shape x +-+-+-+ |4|3|2| +-+-+-+
Součin prvek po prvku (nejedná se o maticový součin!):
x*x +--+--+ +---+---+ +---+---+ +---+---+ | 1| 4| | 49| 64| |169|196| |361|400| +--+--+ +---+---+ +---+---+ +---+---+ | 9|16| | 81|100| |225|256| |441|484| +--+--+ +---+---+ +---+---+ +---+---+ |25|36| |121|144| |289|324| |529|576| +--+--+ +---+---+ +---+---+ +---+---+
Konstrukce šestirozměrného pole 2×2×2×2×2×2 prvky:
2 2 2 2 2 2 reshape count 64 +-+-+ +-+-+ +--+--+ +--+--+ |1|2| |5|6| |17|18| |21|22| +-+-+ +-+-+ +--+--+ +--+--+ |3|4| |7|8| |19|20| |23|24| +-+-+ +-+-+ +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ | 9|10| |13|14| |25|26| |29|30| +--+--+ +--+--+ +--+--+ +--+--+ |11|12| |15|16| |27|28| |31|32| +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ |33|34| |37|38| |49|50| |53|54| +--+--+ +--+--+ +--+--+ +--+--+ |35|36| |39|40| |51|52| |55|56| +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ +--+--+ |41|42| |45|46| |57|58| |61|62| +--+--+ +--+--+ +--+--+ +--+--+ |43|44| |47|48| |59|60| |63|64| +--+--+ +--+--+ +--+--+ +--+--+
Funkce display zobrazí pole tak, jak by se dalo zapsat zpět do terminálu pro jeho konstrukci (jedná se tedy vlastně o serializaci):
x is 2 3 reshape count 6 x 1 2 3 4 5 6 display x 2 3 reshape 1 2 3 4 5 6
Dtto pro jiné pole:
x is 2 2 2 2 2 2 reshape count 64 display x 2 2 2 2 2 2 reshape 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
Odlišný (řekněme alternativní) způsob předání parametrů funkcím, který se podobá běžným programovacím jazykům:
reshape [3 4,count 12] +-+--+--+--+ |1| 2| 3| 4| +-+--+--+--+ |5| 6| 7| 8| +-+--+--+--+ |9|10|11|12| +-+--+--+--+ sum[reshape [3 4,count 12], 100] +---+---+---+---+ |101|102|103|104| +---+---+---+---+ |105|106|107|108| +---+---+---+---+ |109|110|111|112| +---+---+---+---+
17. Definice funkcí
Velmi elegantně je v programovacím jazyku Nial vyřešena problematika definice funkcí. Plně je pochopitelně podporována programovací technika tacit programming, ale i částečná realizace funkcí atd.
Příkladem může být definice funkce pro přičtení jedničky k operandu:
inc is (1 +)
Jedná se o plnohodnotnou funkci s jediným operandem:
inc 10 11 inc 1 2 3 4 2 3 4 5
Příkladem využití tacit programmingu může být definice funkce pro výpočet faktoriálu, jejíž tělo je tvořeno nedokončeným výrazem, kterému je zapotřebí předat počet prvků pro funkci count:
fact is * count fact 10 3628800
Faktoriál lze ovšem realizovat i klasickým rekurzivním výpočtem – všechna důležitá klíčová slova jsou podporována:
fact2 is op x {if x = 0 then 1 else x * fact (x - 1) endif} fact2 10 3628800
V definici funkce fact2 je specifikováno, že akceptuje jeden operand. Ovšem velmi snadno lze realizovat funkci s oběma operandy:
add is op x y {x + y}
Funkce se posléze použije stejně, jako jakákoli další „operátorová funkce“ se dvěma operandy:
1 add 2 3 1 2 3 add 3 4 5 4 6 8
18. Závěrečné zhodnocení
Jak jsme si již v dnešním článku několikrát řekli, patří Nial mezi programovací jazyky, které zcela evidentně přebírají myšlenky z APL a do jisté míry i z funkcionálních programovacích jazyků. Nial se ovšem i přes svoje stáří nikdy nerozšířil mezi mainstream a pravděpodobně k tomu ani nedojde – nejvíce se v této oblasti používá APL (přesněji řečeno jeho varianta nazvaná Dyalog) a taktéž programovací jazyk Q odvozený od K (jehož pozice je v dané nice neotřesitelná). Na druhou stranu se jedná (v porovnání s konkurencí) o velmi čitelný jazyk, takže by se mohlo jednat o dobrou volbu pro ty vývojáře, kteří se chtějí seznámit se zajímavým světem array programmingu. Pokud vás ovšem zajímá, jak by mohl vypadat skutečně moderně pojatý jazyk z této oblasti, je podle mého názoru zajímavější se zaměřit na jazyk BQN, popř. zjistit, jak byly myšlenky převzaté z APL realizovány například v jazyku Julia.
19. Předchozí články o rozsáhlém světu „array programmingu“
Programovacími jazyky, které jsou z větší či menší míry odvozeny od APL, jsme se již na stránkách Roota zabývali v několika článcích. Odkazy na tyto články naleznete pod odstavcem:
- Jazyky umožňující operace s poli aneb rozsáhlý svět „array programmingu“
https://www.root.cz/clanky/jazyky-umoznujici-operace-s-poli-aneb-rozsahly-svet-bdquo-array-programmingu-ldquo/ - Specializované jazyky pro práci s N-dimenzionálními poli: jazyk J
https://www.root.cz/clanky/specializovane-jazyky-pro-praci-s-n-dimenzionalnimi-poli-jazyk-j/ - Programovací jazyky odvozené od APL: BQN a ivy aneb 1~×`1↓↕10
https://www.root.cz/clanky/programovaci-jazyky-odvozene-od-apl-bqn-a-ivy-aneb-1–1–10/ - Programovací jazyk K: důkaz, že mezi námi žijí mimozemšťané
https://www.root.cz/clanky/programovaci-jazyk-k-dukaz-ze-mezi-nami-ziji-mimozemstane/ - Programovací jazyk K: důkaz, že mezi námi žijí mimozemšťané (dokončení)
https://www.root.cz/clanky/programovaci-jazyk-k-dukaz-ze-mezi-nami-ziji-mimozemstane-dokonceni/ - Programování mainframů: jazyk APL
https://www.root.cz/clanky/programovani-mainframu-jazyk-apl/ - Programovací jazyk APL: programování bez smyček
https://www.root.cz/clanky/programovaci-jazyk-apl-programovani-bez-smycek/ - Programovací jazyk APL – dokončení
https://www.root.cz/clanky/programovaci-jazyk-apl-dokonceni/ - Oslava 55 let od vzniku první implementace jazyka APL
https://www.root.cz/clanky/oslava-55-let-od-vzniku-prvni-implementace-programovaciho-jazyka-apl/
20. Odkazy na Internetu
- Nial: A powerful, interactive array language with support for flexible multiparadigm code
https://www.nial-array-language.org/ - Nial: dokumentace
https://www.nial-array-language.org/ndocs/ - Nial na GitHubu
https://github.com/niallang/Nial_Development - Nial na Rosetta Code
https://rosettacode.org/wiki/Category:Nial - Array language comparisons
https://github.com/codereport/array-language-comparisons - K language – an introduction
http://www.math.bas.bg/bantchev/place/k.html - K7 Tutorial
https://cs.nyu.edu/~shasha/papers/tutorial - An Interview with Arthur Whitney, Kx CEO and Developer of Kx Technology, January 4, 2004
https://web.archive.org/web/20150813004101/http://kx.com/arthur-interview.php - A Shallow Introduction to the K Programming Language
https://web.archive.org/web/20130801233812/http://www.kuro5hin.org/story/2002/11/14/22741/791 - A Conversation with Arthur Whitney
https://queue.acm.org/detail.cfm?id=1531242 - Anecdote about Arthur Whitney
https://news.ycombinator.com/item?id=13590065 - K – list of idioms
https://github.com/kevinlawler/kona/wiki/Idioms - Appendix A. Incunabulum
http://keiapl.org/rhui/remember.htm#incunabulum - K code study
https://docs.google.com/document/d/1W83ME5JecI2hd5hAUqQ1BVF32wtCel8zxb7WPq-D4f8/edit - K tutorial
https://github.com/kevinlawler/kona/wiki/Tutorial - K by EXAMPLE
http://vrabi.web.elte.hu/k/kbyeg.k - BQN: An APL Variant from Marshall Lochbaum (mlochbaum.github.io)
https://news.ycombinator.com/item?id=24167804 - Raytracer in 7 lines in K
http://www.nsl.com/k/ray/ray.k - Marshall Lochbaum
https://www.aplwiki.com/wiki/Marshall_Lochbaum - BQN
https://www.aplwiki.com/wiki/BQN - Co-dfns
https://www.aplwiki.com/wiki/Co-dfns - Array model
https://www.aplwiki.com/wiki/Array_model#Based_array_theory - Fonts for BQN
https://mlochbaum.github.io/BQN/fonts.html - Leading axis theory
https://www.aplwiki.com/wiki/Leading_axis_theory - A based system for general arrays
https://dl.acm.org/doi/abs/10.1145/586656.586663 - APL – A Glimpse of Heaven (2006)
https://news.ycombinator.com/item?id=19325361 - APL and J
https://crypto.stanford.edu/~blynn/c/apl.html - ivy (dokumentace)
https://pkg.go.dev/robpike.io/ivy#section-readme - ivy na GitHubu
https://github.com/robpike/ivy/ - Ivy na APL wiki
https://aplwiki.com/wiki/Ivy - Implementing a bignum calculator (slajdy)
https://talks.godoc.org/github.com/robpike/ivy/talks/ivy.slide#1 - Implementing a bignum calculator – Rob Pike – golang-syd November 2014
https://www.youtube.com/watch?v=PXoG0WX0r_E - Rob Pike na Wikipedii
https://en.wikipedia.org/wiki/Rob_Pike - Rob Pike na cat-v
http://genius.cat-v.org/rob-pike/ - Jazyky umožňující operace s poli aneb rozsáhlý svět „array programmingu“
https://www.root.cz/clanky/jazyky-umoznujici-operace-s-poli-aneb-rozsahly-svet-bdquo-array-programmingu-ldquo/ - Programovací technika nazvaná tacit programming
https://www.root.cz/clanky/programovaci-technika-nazvana-tacit-programming/ - Oslava 55 let od vzniku první implementace jazyka APL
https://www.root.cz/clanky/oslava-55-let-od-vzniku-prvni-implementace-programovaciho-jazyka-apl/ - NuVoc
https://code.jsoftware.com/wiki/NuVoc - J (programming language) [Wikipedia]
https://en.wikipedia.org/wiki/J_%28programming_language%29 - J – Absolutely Essential Terms
https://code.jsoftware.com/wiki/Vocabulary/AET - J – Atoms and Arrays
https://code.jsoftware.com/wiki/Vocabulary/Nouns#Atom - Why J
https://www.jsoftware.com/help/primer/why_j.htm - What is an Array?
https://vector.org.uk/what-is-an-array/ - Comments
http://www.gavilan.edu/csis/languages/comments.html - Vector (Wolfram MathWorld)
https://mathworld.wolfram.com/Vector.html - n-Tuple (Wolfram MathWorld)
https://mathworld.wolfram.com/n-Tuple.html - n-Vector (Wolfram MathWorld)
https://mathworld.wolfram.com/n-Vector.html - Matrix (Wolfram MathWorld)
https://mathworld.wolfram.com/Matrix.html - Array (Wolfram MathWorld)
https://mathworld.wolfram.com/Array.html - ND Arrays (Tensors) in different languages
https://www.youtube.com/watch?v=WbpbEilgQBc - Extending APL to Infinity\
https://www.jsoftware.com/papers/eem/infinity.htm - Vector Library (R7RS-compatible)
https://srfi.schemers.org/srfi-133/srfi-133.html - Vectors (pro Gauche)
https://practical-scheme.net/gauche/man/gauche-refe/Vectors.html - Kawa: Compiling Scheme to Java
https://www.mit.edu/afs.new/sipb/project/kawa/doc/kawa-tour.html - Kawa in Languages shootout
http://per.bothner.com/blog/2010/Kawa-in-shootout/ - Kawa 2.0 Supports Scheme R7RS
https://developers.slashdot.org/story/14/12/13/2259225/kawa-20-supports-scheme-r7rs/ - Kawa — fast scripting on the Java platform
https://lwn.net/Articles/623349/ - Incanter is a Clojure-based, R-like platform for statistical computing and graphics.
http://incanter.org/ - Evolution of incanter (Gource Visualization)
https://www.youtube.com/watch?v=TVfL5nPELr4 - Questions tagged [incanter] (na Stack Overflow)
https://stackoverflow.com/questions/tagged/incanter?sort=active - Data Sorcery with Clojure
https://data-sorcery.org/contents/ - Back to the Future: Lisp as a Base for a Statistical Computing System
https://rd.springer.com/chapter/10.1007/978–3–7908–2084–3_2 - Incanter Cheat Sheet
http://incanter.org/docs/incanter-cheat-sheet.pdf - Back to the Future: Lisp as a Base for a Statistical Computing System (celá verze článku)
https://www.researchgate.net/publication/227019917_Back_to_the_Future_Lisp_as_a_Base_for_a_Statistical_Computing_System - BQN: finally, an APL for your flying saucer
https://mlochbaum.github.io/BQN/ - Is BQN stable?
https://mlochbaum.github.io/BQN/commentary/stability.html - Specification: BQN system-provided values
https://mlochbaum.github.io/BQN/spec/system.html - Tutorial: BQN expressions
https://mlochbaum.github.io/BQN/tutorial/expression.html - BQN primitives
https://mlochbaum.github.io/BQN/doc/primitive.html - Function trains
https://mlochbaum.github.io/BQN/doc/train.html - BQN community links
https://mlochbaum.github.io/BQN/community/index.html - BQN UV
https://observablehq.com/@lsh/bqn-uv - APL Wiki
https://aplwiki.com/wiki/ - The Array Cast
https://www.arraycast.com/episodes/episode-03-what-is-an-array - EnthusiastiCon 2019 – An Introduction to APL
https://www.youtube.com/watch?v=UltnvW83_CQ - Dyalog
https://www.dyalog.com/ - Try APL!
https://tryapl.org/ - Lisp-Stat Information
http://homepage.cs.uiowa.edu/~luke/xls/xlsinfo/ - Sample Plots in Incanter
https://github.com/incanter/incanter/wiki/Sample-Plots-in-Incanter#line - vectorz-clj
https://github.com/mikera/vectorz-clj - vectorz – Examples
https://github.com/mikera/vectorz-clj/wiki/Examples - Basic Vector and Matrix Operations in Julia: Quick Reference and Examples
https://queirozf.com/entries/basic-vector-and-matrix-operations-in-julia-quick-reference-and-examples - Vectors and matrices in Julia
https://fncbook.github.io/v1.0/linsys/demos/matrices-julia.html - Array vs Matrix in R Programming
https://www.geeksforgeeks.org/array-vs-matrix-in-r-programming/ - Concurrency (computer science)
https://en.wikipedia.org/wiki/Category:Concurrency_%28computer_science%29 - Koprogram
https://cs.wikipedia.org/wiki/Koprogram - Coroutine
https://en.wikipedia.org/wiki/Coroutine - Coroutines in C
http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html - S-expression (Wikipedia)
https://en.wikipedia.org/wiki/S-expression - S-Expressions (Rosetta Code)
http://rosettacode.org/wiki/S-Expressions - Introducing Julia/Metaprogramming
https://en.wikibooks.org/wiki/Introducing_Julia/Metaprogramming - Tutorial for the Common Lisp Loop Macro
http://www.ai.sri.com/pkarp/loop.html - Clojure Macro Tutorial (Part I, Getting the Compiler to Write Your Code For You)
http://www.learningclojure.com/2010/09/clojure-macro-tutorial-part-i-getting.html - Clojure Macro Tutorial (Part II: The Compiler Strikes Back)
http://www.learningclojure.com/2010/09/clojure-macro-tutorial-part-ii-compiler.html - Clojure Macro Tutorial (Part III: Syntax Quote)
http://www.learningclojure.com/2010/09/clojure-macro-tutorial-part-ii-syntax.html - Clojure Macros and Metaprogramming
http://clojure-doc.org/articles/language/macros.html - Fatvat – Exploring functional programming: Clojure Macros
http://www.fatvat.co.uk/2009/02/clojure-macros.html - CS 2101 Parallel Computing with Julia
https://www.coursehero.com/file/11508091/CS-2101-Parallel-Computing-with-Julia/ - Julia By Example
https://samuelcolvin.github.io/JuliaByExample/ - Array Programming
https://en.wikipedia.org/wiki/Array_programming - Discovering Array Languages
http://archive.vector.org.uk/art10008110 - no stinking loops – Kalothi
http://www.nsl.com/ - Vector (obsahuje odkazy na články, knihy a blogy o programovacích jazycích APL, J a K)
http://www.vector.org.uk/ - APL Interpreters
http://www.vector.org.uk/?area=interpreters - APL_(programming_language
http://en.wikipedia.org/wiki/APL_(programming_language - APL FAQ
http://www.faqs.org/faqs/apl-faq/ - APL FAQ (nejnovější verze)
http://home.earthlink.net/~swsirlin/apl.faq.html - A+
http://www.aplusdev.org/ - APLX
http://www.microapl.co.uk/ - FreeAPL
http://www.pyr.fi/apl/index.htm - Learning J (Roger Stokes)
http://www.jsoftware.com/help/learning/contents.htm - J: a modern, high-level, general-purpose, high-performance programming language
http://www.jsoftware.com/ - K, Kdb: an APL derivative for Solaris, Linux, Windows
http://www.kx.com - openAPL (GPL)
http://sourceforge.net/projects/openapl - Parrot APL (GPL)
http://www.parrotcode.org/ - Learning J (Roger Stokes)
http://www.jsoftware.com/help/learning/contents.htm - Rosetta Code
http://rosettacode.org/wiki/Main_Page - Why APL
http://www.acm.org/sigapl/whyapl.htm - Introducing Julia/Functions
https://en.wikibooks.org/wiki/Introducing_Julia/Functions - Functions (Julia documentation)
https://docs.julialang.org/en/v1/manual/functions/ - Evaluate binomial coefficients
http://rosettacode.org/wiki/Evaluate_binomial_coefficients - Ackermann function
http://rosettacode.org/wiki/Ackermann_function - Julia (front page)
http://julialang.org/ - Julia – dokumentace
http://docs.julialang.org/ - Julia – repositář na GitHubu
https://github.com/JuliaLang/julia - Julia (programming language)
https://en.wikipedia.org/wiki/Julia_%28programming_language%29 - IJulia
https://github.com/JuliaLang/IJulia.jl - Introducing Julia
https://en.wikibooks.org/wiki/Introducing_Julia - Julia: the REPL
https://en.wikibooks.org/wiki/Introducing_Julia/The_REPL - Month of Julia
https://github.com/DataWookie/MonthOfJulia - Learn X in Y minutes (where X=Julia)
https://learnxinyminutes.com/docs/julia/ - New Julia language seeks to be the C for scientists
http://www.infoworld.com/article/2616709/application-development/new-julia-language-seeks-to-be-the-c-for-scientists.html - Julia: A Fast Dynamic Language for Technical Computing
http://karpinski.org/publications/2012/julia-a-fast-dynamic-language - The LLVM Compiler Infrastructure
http://llvm.org/ - Julia: benchmarks
http://julialang.org/benchmarks/ - Type system
https://en.wikipedia.org/wiki/Type_system - Half-precision floating-point format
https://en.wikipedia.org/wiki/Half-precision_floating-point_format - Dartmouth BASIC
https://en.wikipedia.org/wiki/Dartmouth_BASIC - BASIC 4th Edition
http://www.bitsavers.org/pdf/dartmouth/BASIC_4th_Edition_Jan68.pdf - VECTRAN
https://encyclopedia2.thefreedictionary.com/VECTRAN - Comparison of programming languages (array)
https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(array) - BASIC at 50
https://www.dartmouth.edu/basicfifty/commands.html - BBC Basic – arrays
http://www.riscos.com/support/developers/bbcbasic/part2/arrays.html - Datová struktura
https://cs.wikipedia.org/wiki/Datov%C3%A1_struktura - SIMD instrukce využívané v moderních mikroprocesorech řady x86
https://www.root.cz/clanky/simd-instrukce-vyuzivane-v-modernich-mikroprocesorech-rady-x86/ - SIMD instrukce v moderních mikroprocesorech řady x86 (2.část: SSE)
https://www.root.cz/clanky/simd-instrukce-v-modernich-mikroprocesorech-rady-x86–2-cast-sse/ - SIMD instrukce v moderních mikroprocesorech řady x86 (3.část: SSE2)
https://www.root.cz/clanky/simd-instrukce-v-modernich-mikroprocesorech-rady-x86–3-cast-sse2/ - Inductive type
https://en.wikipedia.org/wiki/Inductive_type - JuliaMono, a font for programming
https://github.com/cormullion/juliamono - It’s arrays all the way down
https://xpqz.github.io/learnapl/array.html - APL vs BQN vs J vs Q vs NumPy vs Julia vs R
https://www.youtube.com/watch?v=8ynsN4nJxzU