Obsah
1. Programovací jazyk K – důkaz, že mezi námi žijí mimozemšťané
3. Arthur Whitney jakožto osobnost v IT
4. Základní vlastnosti programovacího jazyka K
5. K = vektory + seznamy + operátory + modifikátory + funkce
6. Překlad volně dostupného interpretru programovacího jazyka K
7. První spuštění interaktivní smyčky REPL jazyka K
8. Skalární hodnoty a základní aritmetické operace podporované jazykem K
10. Aritmetické operace s vektory
11. Proměnné a některé složitější operace se skaláry a vektory
12. Konstrukce vektoru algoritmem
13. Převod hodnoty do zvolené číselné soustavy
14. Vyhledávání hodnot ve vektorech
16. Modifikátory over, scan a each
18. Náhrada programových smyček pomocí modifikátorů
1. Programovací jazyk K – důkaz, že mezi námi žijí mimozemšťané
„In C I never learned to use the debugger so I used to never make mistakes“
Arthur Whitney
V dnešním článku se budeme zabývat programovacím jazykem, který se jmenuje K. Jedná se o minimalisticky pojatý programovací jazyk, mezi jehož ideové předchůdce patří již popsaný jazyk APL, ovšem taktéž jazyk Scheme. A výsledek, který vznikl kombinací APL+Scheme, je velmi zajímavý. Důležité je, že se v žádném případě nejedná jen o akademický jazyk (spíš naopak – většinu zastánců IT jakožto vědy existence K spíše irituje). Tento jazyk je totiž základem nástrojů vyvíjených společností Kx Systems, především pak velmi rychlé sloupcové databáze kdb+ (je tedy zřejmé, kde se vzalo jméno této společnosti – ostatně autor jazyka K je současně spoluzakladatel této firmy). Kx Systems nad kdb+ a jazykem K vyvíjí nástroje pro analýzu trhů, on-line obchodování (jednalo se o jednu z prvních společností, která tuto technologii nabízela), nástroje pro telekomunikační průmysl apod.
2. Stručná historie jazyka K
„I never comment anything because I'm always trying to make it so the code itself is the comment.“
Arthur Whitney
Autorem programovacího jazyka K je Arthur Whitney, což je v IT možná poněkud méně známá, ale o to zajímavější a kontroverzní osobnost – ostatně viz přiložené Arthurovy citáty. Arthur Whitney spolupracoval s Kenem Iversonem na vývoji programovacího jazyka APL, což paradoxně původně neměl být programovací jazyk, ale způsob zápisu matematických výrazů a algoritmů s využitím nové jednotné notace. Arthur Whitney kromě práce na APL vyvinul i interpret jazyka Scheme a právě znalost Scheme se později promítla do návrhu jazyka K. Kromě APL vyvinul Arthur Whitney pro společnost I.P.Sharp Associates i programovací jazyk nazvaný A+, který je jakýmsi mezikrokem mezi APL a K. A+ je určen především pro zpracování velkého množství dat, což je vlastnost, která tento jazyk (po 25 letech) opět uvádí na scénu.
V roce 1993 Arthur Whitney vyvinul programovací jazyk K a poté založil již v úvodu zmíněnou společnost Kx Systems, která dodnes existuje a zdá se být velmi úspěšná. Nad jazykem K byla vyvinuta sloupcová databáze kdb+, která je mimochodem „loop-free“, tj. v jejím zdrojovém kódu nenajdeme ani jednu explicitně zapsanou programovou smyčku! Interpret i překladač jazyka K lze ze stránek Kx Systems získat, ovšem nikoli pod svobodnou licencí. Existují však i jiné varianty K.
3. Arthur Whitney jakožto osobnost v IT
„The K binary weighs in at about 50Kb. Someone asked about the interpreter source code. A frown flickered across the face of our visitor from Microsoft: what could be interesting about that? “The source is currently 264 lines of C,” said Arthur. I thought I heard a sotto voce “that’s not possible.” Arthur showed us how he had arranged his source code in five files so that he could edit any one of them without scrolling. “Hate scrolling,” he mumbled.“
Pokud bychom měli charakterizovat styl, s jakým k vývoji (stále) přistupuje Arthur Whitney, je to snaha o kombinaci několika základních operací společně s k tomu vhodnými datovými strukturami tak, aby výsledkem byl minimalistický kód, a to bez ohledu na čitelnost výsledného kódu nebo jeho testovatelnost. Ideálním cílem je, aby se kód (jakékoli) aplikace vešel na jedinou obrazovku :-) – viz též motto této kapitoly. Tato snaha je patrná i při pohledu na úryvky zdrojového kódu samotného interpretru a překladače jazyka K. Původní Arthurův kód vypadá následovně (ano, jedná se o standardní céčko!):
#include "k.h" I MZ[31]={1};Z I *MM[31];mi(){MZ[7]=MZ[13]=MZ[19]=MZ[25]=2;DO(30,MZ[i+1]+=MZ[i]*2)} Z mmr(n,i){if(i<18)i=18;R err(2,n),tmp((MZ[i]+2)<<2),1;} /* Dan MZ[i+1]? */ C *mab(m)unsigned m;{I *p,*r,i=2,n=m;for(n=(n+3)>>4;n;n>>=1)++i; do{if(p=MM[i])R MM[i]=(I*)*p,(C*)p;for(n=i;n<30;)if(p=MM[++n]){ for(MM[n]=(I*)*p,p[-1]=i;i<n;)r=p+MZ[--n],MM[r[-1]=n]=r,*r=0;R(C*)p;} if(mc()>=i)continue;} while(mmr(m,i));} I *ma(m){R(I*)mab(m<<2);} mf(p)I *p;{I i=p[-1];*p=(I)MM[i],MM[i]=p;} mb(p,n)I *p;{I i=31,j;for(n-=2,++p;i--;)if(j=MZ[i],j<=n)n-=j,*p=i,mf(p+1),p+=j;} mc(){R 0;} I *mz(){Z I b[31];I *p;DO(31,for(b[i]=0,p=MM[i];p;p=(I*)*p)++b[i])R b;}
Naproti tomu po přepisu do „lidské“ podoby vypadá zdrojový kód takto (je samozřejmě mnohem delší, ovšem lze ho testovat, krokovat atd.).
Mimochodem, v tomto dokumentu jsou postupně popsána jednotlivá makra, která jsou použita pro vytvoření takto kompaktního kódu:
#define R return #define P(b,a...) if(b)return(a); #define N(n,a...) {I i=0,_n=(n);while(i<_n){a;++i;}} #define W(b...) while((b)) //while #define $(b,a...) if(b){a;}else //cond #define C(i,a...) case i:{a;}break; //case #define S(i,c,a...) switch(i){c default:a;} //switch
4. Základní vlastnosti programovacího jazyka K
„Ken believed that notation should be as high level as possible because, for example, if matrix product is plus-dot-times, there's no question about that being correct.“
Arthur Whitney
Arthur Whitney navrhl jazyk K tak, že do něj vybral esenci z jazyků APL a Scheme. Ovšem výsledkem není jakýsi kočkopes, jak by se mohlo zdát, ale unikátní minimalisticky navržený programovací jazyk. Většina základních operátorů je reprezentována jedním či dvěma ASCII znaky, a díky kompaktnímu zápisu vypadá zdrojový kód K jako šum na lince (což není chyba, ale vlastnost, kterou přiznávají i skalní příznivci jazyka K). V programech se typicky pracuje s vektory a zcela jsou omezeny smyčky a do značné míry i podmínky.
Do jaké míry je K kompaktní a (zdánlivě) nečitelný, dokazuje asi nejlépe implementace plnohodnotného raytraceru na pouhých sedmi řádcích kódu (zbytek jsou prázdné řádky a komentáře). Ostatně posuďte sami na http://www.nsl.com/k/ray/ray.k.
5. K = vektory + seznamy + operátory + modifikátory + funkce
„What happened with A+?
Within a month or two we were using it to analyze our historical data. A few months later we used it to implement the trading system which bought and sold $100 million worth of shares every day“
Arthur Whitney
Jazyk K je z velké míry postaven nad datovou strukturou seznam; zde je vidět inspirace v jazyku Scheme. Seznamy jsou heterogenní datové struktury, ovšem v případě, že jsou všechny prvky stejného typu, dojde k uložení seznamů velmi efektivním způsobem – typ prvku se uloží jen pro celý seznam a mezi prvky nejsou výplně. Výsledku pak říkáme vektor. Z vektorů lze skládat vícerozměrné matice, i když se ve většině případů pracuje „pouze“ s dvourozměrnými a trojrozměrnými maticemi (poli). V jazyku K nalezneme taktéž možnost definice uživatelských funkcí, přičemž funkce jsou plnohodnotným datovým typem – opět podobně jako ve Scheme.
Podobně jako v případě programovacího jazyka APL či od něj odvozeného jazyka J, obsahuje i programovací jazyk K velké množství primitivních (základních) operátorů. Ty však nejsou reprezentovány speciálními symboly, ale jedním nebo více nealfanumerickými ASCII znaky, takže jejich zápis i editace je jednodušší, než tomu bylo v případě APL (na druhou stranu nevypadají zapsané algoritmy tak efektně :-). Vestavěné operátory mohou akceptovat buď jeden parametr (monadické operátory) nebo parametry dva (operátory dyadické). Symbol monadických operátorů je uveden v prefixové podobě, tj. vždy před svým parametrem, zatímco dyadické operátory jsou zapisovány v podobě infixové – mezi oba parametry (operandy), čímž se efektivně v mnoha případech eliminuje nutnost použití závorek. Znaky, kterými jsou vestavěné operátory ve zdrojovém kódu reprezentovány, jsou většinou použity minimálně dvakrát – jednou pro zápis monadického operátoru, podruhé pro zápis operátoru dyadického, jehož význam bývá v menší či větší míře podobný příslušnému operátoru monadickému.
6. Překlad volně dostupného interpretru programovacího jazyka K
„We had a portfolio that was a billion dollars: half a billion long, half a billion short. We were trading every second electronically. The data set was a terabyte, but we compressed it down. It was pairs trading, and I wrote an APL to do all of that—the big database and the realtime trading—so our entire department was using my language.“
Arthur Whitney
Oficiální interpret a současně i překladač programovacího jazyka K je možné, společně s mnoha dalšími nástroji (i databází), získat na stránce https://kx.com/developers/download-licenses/. My však, už jen proto, že se nacházíme na stránkách Roota, použijeme odlišnou variantu jazyka K, která je distribuována se zdrojovými kódy a pod pro vývojáře příjemnější licencí. Tato varianta je dostupná na GitHubu (https://github.com/kevinlawler/kona) a pro její zprovoznění je zapotřebí pouze překladač programovacího jazyka C (a pochopitelně celý ekosystém postavený okolo tohoto překladače).
Nejprve je pochopitelně nutné repositář se zdrojovými kódy jazyka K naklonovat do pracovního adresáře:
$ git clone git@github.com:kevinlawler/kona.git Cloning into 'kona'... remote: Enumerating objects: 6516, done. remote: Counting objects: 100% (215/215), done. remote: Compressing objects: 100% (84/84), done. remote: Total 6516 (delta 136), reused 204 (delta 131), pack-reused 6301 Receiving objects: 100% (6516/6516), 2.49 MiB | 691.00 KiB/s, done. Resolving deltas: 100% (4696/4696), done.
Následně se přesuneme do vytvořeného adresáře:
$ cd cona
A použijeme standardní make pro překlad a slinkování interpretru:
$ make OS="linux" echo "#define KBUILD_DATE \"`date +%Y-%m-%d`\"" >src/kbuild.h cc -g -pthread -O3 -c -o src/0.o src/0.c cc -g -pthread -O3 -c -o src/bswap.o src/bswap.c cc -g -pthread -O3 -c -o src/c.o src/c.c cc -g -pthread -O3 -c -o src/getline.o src/getline.c cc -g -pthread -O3 -c -o src/mt.o src/mt.c cc -g -pthread -O3 -c -o src/p.o src/p.c cc -g -pthread -O3 -c -o src/r.o src/r.c cc -g -pthread -O3 -c -o src/k.o src/k.c cc -g -pthread -O3 -c -o src/kc.o src/kc.c cc -g -pthread -O3 -c -o src/kx.o src/kx.c ... ... ... cc -g -pthread -O3 -c -o src/vf.o src/vf.c cc -g -pthread -O3 -c -o src/vg.o src/vg.c cc -g -pthread -O3 -c -o src/vq.o src/vq.c cc -g -pthread -O3 -c -o src/main.o src/main.c cc -g -pthread -O3 src/0.o src/bswap.o src/c.o src/getline.o src/mt.o src/p.o src/r.o src/k.o src/kc.o src/kx.o src/kg.o src/km.o src/kn.o src/ko.o src/ks.o src/v.o src/va.o src/vc.o src/vd.o src/vf.o src/vg.o src/vq.o src/main.o -o k -lm -ldl cc -g -pthread -O0 -g3 -DDEBUG -Wall -c -o src/0.t.o src/0.c cc -g -pthread -O0 -g3 -DDEBUG -Wall -c -o src/bswap.t.o src/bswap.c cc -g -pthread -O0 -g3 -DDEBUG -Wall -c -o src/c.t.o src/c.c cc -g -pthread -O0 -g3 -DDEBUG -Wall -c -o src/getline.t.o src/getline.c cc -g -pthread -O0 -g3 -DDEBUG -Wall -c -o src/mt.t.o src/mt.c cc -g -pthread -O0 -g3 -DDEBUG -Wall -c -o src/p.t.o src/p.c cc -g -pthread -O0 -g3 -DDEBUG -Wall -c -o src/r.t.o src/r.c ... ... ... cc -g -pthread -O0 -g3 -DDEBUG -Wall -c -o src/tests.t.o src/tests.c cc -g -pthread -O0 -g3 -DDEBUG -Wall src/0.t.o src/bswap.t.o src/c.t.o src/getline.t.o src/mt.t.o src/p.t.o src/r.t.o src/k.t.o src/kc.t.o src/kx.t.o src/kg.t.o src/km.t.o src/kn.t.o src/ko.t.o src/ks.t.o src/v.t.o src/va.t.o src/vc.t.o src/vd.t.o src/vf.t.o src/vg.t.o src/vq.t.o src/main.t.o src/tests.t.o -o k_test -lm -ldl
Výsledkem překladu by měl být spustitelný soubor k a taktéž k_test:
$ ls -l total 2912 drwxrwxr-x 2 ptisnovs ptisnovs 120 Jul 18 17:02 bench -rwxrwxr-x 1 ptisnovs ptisnovs 1625848 Jul 18 17:03 k -rw-rw-r-- 1 ptisnovs ptisnovs 156102 Jul 18 17:02 Kona.png -rwxrwxr-x 1 ptisnovs ptisnovs 1171664 Jul 18 17:03 k_test -rw-rw-r-- 1 ptisnovs ptisnovs 772 Jul 18 17:02 LICENSE -rw-rw-r-- 1 ptisnovs ptisnovs 6756 Jul 18 17:02 Makefile drwxrwxr-x 2 ptisnovs ptisnovs 120 Jul 18 17:02 misc -rw-rw-r-- 1 ptisnovs ptisnovs 4482 Jul 18 17:02 README.md drwxrwxr-x 3 ptisnovs ptisnovs 2180 Jul 18 17:03 src drwxrwxr-x 2 ptisnovs ptisnovs 100 Jul 18 17:02 verb
V předchozích kapitolách jsme si řekli, že K je poměrně malý jazyk, čemuž ale neodpovídá velikost výsledného binárního souboru. Podle mých kritérií se musí „malý“ jazyk vejít na disketu :-) Takže zkusme:
$ strip k
Výsledkem je skutečně soubor, který se vejde i na disketu s formátem double density:
$ ls -l k -rwxrwxr-x 1 ptisnovs ptisnovs 341712 Jul 18 17:11 k
Takto upravený interpret použijeme v navazujících kapitolách při popisu různých vlastností programovacího jazyka K.
Interpret jazyka K není slinkován s knihovnami typu readline. Proč je to však tak důležité, že se o tom explicitně zmiňujeme? Nepodpora readline, mj. znamená, že neexistuje historie příkazového řádku, není možné používat editační příkazy typu Ctrl+A, Ctrl+E, ani vyhledávání v dříve zadaných příkazech pomocí Ctrl+R atd. A navíc nefunguje automatické doplňování jmen symbolů klávesou Tab. Tyto vlastnosti, které dnes od REPLů prakticky automaticky očekáváme, je možné do jisté míry doplnit externím nástrojem rlwrap. Tomu můžeme v případě potřeby předat soubor se symboly pro automatické doplňování. Nástroj rlwrap se instaluje snadno:
$ dnf install rlwrap Last metadata expiration check: 0:33:16 ago on Sat 09 Apr 2022 06:45:42 AM EDT. Dependencies resolved. ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: rlwrap x86_64 0.45.2-1.fc34 updates 132 k Installing dependencies: perl-File-Slurp noarch 9999.32-3.fc34 beaker-Fedora 31 k perl-lib x86_64 0.65-477.fc34 updates 25 k Transaction Summary ================================================================================ Install 3 Packages Total download size: 188 k Installed size: 399 k Is this ok [y/N]: y Downloading Packages: (1/3): perl-File-Slurp-9999.32-3.fc34.noarch.rp 3.6 MB/s | 31 kB 00:00 (2/3): perl-lib-0.65-477.fc34.x86_64.rpm 197 kB/s | 25 kB 00:00 (3/3): rlwrap-0.45.2-1.fc34.x86_64.rpm 649 kB/s | 132 kB 00:00 -------------------------------------------------------------------------------- Total 142 kB/s | 188 kB 00:01
7. První spuštění interaktivní smyčky REPL jazyka K
„You like short programs and simple languages, some might say your languages are cryptic. Terse, yes. Cryptic, no. I like to simplify things: shorter programs, fewer primitives, smaller systems to run on, all of which makes for more productive, more cost-efficient programming.“
Interpret programovacího jazyka K spustíme příkazem k bez uvedení dalších parametrů:
$ ./k
Popř. můžeme volání interpretru „obalit“ nástrojem rlwrap, který zajistí historii příkazového řádku, vyhledávání v historii, editaci příkazového řádku atd.:
$ rlwrap ./k
Měla by se zobrazit jednořádková úvodní zpráva následovaná výzvou (prompt):
kona \ for help. \\ to exit.
Příkazem \ si zkusíme zobrazit nápovědu. Ta je opět velmi stručná:
Backslash Commands: \0 datatypes help \+ verb help \' adverb help \: I/O verb help \_ reserved word help \. assignment/amend, function, control flow help \b [s|t] show/set break mode (stop|trace|none) \d [d|^] change k directory (^=previous) \e [n] show/set error flag (0=off,1=on,2=exit) \l f load script f or f.k \p [n] show/set print precision (0=full) \r [s] show/set random seed (0=random) \s f step script f or f.k \t [n] show/set timer interval in msec (0=disable) calls niladic .m.ts \t e measure runtime of some k expression \v [d|^] show k directory (^=previous) \w show workspace resources used \[cmd] system command (also \[ cmd]), \echo hello \\ exit (or ctrl+d)
Samotný komentář se zapisuje za znak /, tedy například takto:
/ toto je komentář
8. Skalární hodnoty a základní aritmetické operace podporované jazykem K
Mezi skalární hodnoty podporované programovacím jazykem K patří především celá čísla, čísla s plovoucí řádovou čárkou, znaky a symboly. Nejvíce operací se pochopitelně provádí s celými čísly popř. s čísly s plovoucí řádovou čárkou. Ukažme si tedy základní aritmetické operace popř. některé funkce používané při numerických výpočtech. Základní aritmetické operace se zapisují v infixové podobě:
1+2 3 2*3 6 4-5 -1
Dělení se ovšem zapisuje znakem %, protože je to znak bližší skutečnému symbolu dělení ÷ navíc je znak / již rezervován pro zápis komentářů (jak již ostatně víme):
6%3 2
Některé operátory mají význam i v monadickém režimu, tedy při použití jediného operátoru. Jedná se o změnu znaménka a výpočet převrácené hodnoty:
-42 42 %2 0.5
Pozor ovšem na to, že operátory jsou vyhodnocovány zprava doleva (jako je tomu v jazyce APL) a nemají stanoveny žádné priority, přesněji řečeno priority všech operátorů jsou totožné a záleží jen na jejich pořadí:
1+2*3 7 3*2+1 9
Pro stanovení priorit můžeme použít závorky:
(3*2)+1 7
Výpočet druhé mocniny a odmocniny je realizován funkcemi, které začínají podtržítkem:
_sqr 2 4.0 _sqrt 2 1.414214
Zajímavé jsou operátory | a &, které zdánlivě slouží k výpočtu logické operace „nebo“ a „a“:
1|0 1 1&0 0
To je sice pravda, ovšem když se nad významem těchto operátorů zamyslíme více, zjistíme, že mohou sloužit i pro nalezení největší a nejmenší hodnoty:
123|456 456 123&456 123
K dispozici je i velké množství dalších často používaných funkcí:
_exp 1 2.718282 _exp 2 7.389056 _log 10 2.302585 2^10 1024.0
9. Seznamy a vektory
„OAG database of flight schedules: OAG published the data, but it had never been automated and placed in a database. In 1980, OAG started providing IP Sharp with the data on tape, and I loaded the tapes into a database and made it available for OLAP-style queries. OAG was big even then–two billion scheduled flights over many years. As far as I know, the database has been in continual 24/7 use since 1980“
Kromě skalárních hodnot (celá čísla, čísla s plovoucí řádovou čárkou, znaky, symboly) podporuje programovací jazyk K i práci se seznamy (ve speciálním případě s vektory). Seznamy se konstruují jednoduše – postačuje všechny prvky zapsat do kulatých závorek (zde je patrná inspirace programovacím jazykem Scheme), přičemž se jednotlivé prvky oddělují pomocí středníků. V případě, že jsou všechny prvky stejného typu (celé číslo, číslo s plovoucí řádovou čárkou, znak), bude seznam uložen ve speciálním formátu, v němž se typ všech prvků uloží jen jedenkrát jako vlastnost celého seznamu. Tento velmi úsporný formát uložení nazýváme vektor (a jedná se o typ, který má jazyk K prakticky totožný s jazykem APL):
(1;2;3;4;5) 1 2 3 4 5
Ve skutečnosti je možné vektory zapisovat ještě jednodušeji než seznamy – pouze vedle sebe zapíšeme hodnoty prvků oddělené mezerami:
1 2 3 4 5 1 2 3 4 5
Totéž platí pro seznamy (a posléze) vektory s čísly s plovoucí řádovou čárkou:
(1.2;3.4;5.6) 1.2 3.4 5.6
popř. jen:
1.2 3.4 5.6 1.2 3.4 5.6
Seznamy, jehož prvky jsou rozdílného typu, jsou stále ukládány v heterogenní podobě (a tedy značně neefektivně, což nám ovšem nemusí v mnoha případech vadit):
(1.2;3;0) (1.2;3;0)
I když to tak nemusí na první pohled vypadat, je i řetězec vlastně vektorem, a to pochopitelně vektorem znaků:
"foobarbaz" "foobarbaz"
Seznamy či vektory lze spojit operátorem čárka:
1 2 3 , 4 5 6 1 2 3 4 5 6
Tento operátor se opět vyhodnocuje zprava doleva:
1 2 3 , 4 5 6 , 7 8 9 1 2 3 4 5 6 7 8 9
10. Aritmetické operace s vektory
Všechny aritmetické operace popsané v osmé kapitole, jsou plně aplikovatelné i na vektory popř. na kombinaci skalární hodnoty a vektoru. Opět se podívejme na několik příkladů.
Součet skaláru s vektorem se provádí prvek po prvku:
1 + 2 3 4 3 4 5
Možná je i druhá kombinace, tedy součet vektoru se skalární hodnotou:
10 20 30 + 5 15 25 35
Sečíst můžeme i dva vektory:
1 2 3 + 4 5 6 5 7 9
V případě, že se provádí součet vektorů (prvek po prvku), musí mít oba vektory stejnou délku – K v tomto případě se tedy neprovádí tzv. broadcasting:
1 2 3 + 4 5 6 7 length error 1 2 3 + 4 5 6 7 ^
V souvislosti s vektory můžeme použít i unární operace, například operaci - pro změnu znaménka všech prvků vektoru:
- 1 2 3 -1 -2 -3
Všechny funkce popsané výše v souvislosti se skalárními číselnými hodnotami jsou použitelné i na prvky vektorů. To se týká i výpočtů druhé mocniny i odmocniny:
_sqr 1 2 3 4 1 4 9 16.0 _sqrt 1 2 3 4 1 1.414214 1.732051 2.0
Operátor # v monadické formě vrací délku vektoru:
#1 2 3 4 5 0 6
11. Proměnné a některé složitější operace se skaláry a vektory
Proměnné se v jazyku K nemusí deklarovat, protože proměnná je vytvořena při prvním přiřazení hodnoty:
x:1 y:2
:x:1+2 3 :y:x*x 9
Operace s proměnnými:
x+y 3
V dalších demonstračních příkladech použijeme dvě proměnné x a y, z nichž každá bude obsahovat čtyřprvkový vektor:
x:1 2 3 4 y:10 20 30 40
Na prvky vektoru lze aplikovat všechny běžné aritmetické operace (jak monadické, tak i dyadické):
-x -1 -2 -3 -4 x+y 11 22 33 44 y%x 10 10 10 10 _sqr x 1 4 9 16.0 _sqrt y 3.162278 4.472136 5.477226 6.324555 %x 1 0.5 0.3333333 0.25
Operace | a & postupně projdou dva vektory a vyhledají největší resp. naopak nejmenší prvek z dané dvojice (!10 vytvoří vektor 0 1 2 3 4 5 6 7 8 9):
x | !10 9 6 9 3 4 5 6 7 8 9 x & !10 0 1 2 3 3 0 4 5 4 7
x|!10 9 6 9 3 4 5 6 7 8 9 x&!10 0 1 2 3 3 0 4 5 4 7
12. Konstrukce vektoru algoritmem
„About two years ago I was introduced to a programming language that I really didn't like: it didn't have continuations, I didn't see any objects, it had too many operators, it didn't have a large community around it, it was strange and different, and it looked like line noise, like Perl, and I don't like Perl. However, I gave it a try.
I had to learn that continuations may not be there, but first-class functions are; it may not have a normal object system, but that is because the language doesn't need it and gets it power by cutting across objects; all the operators are the functions that make up its standard library; it's community may not be large, but it is incredibly intelligent; it only looks strange until you understand its concepts; and well, it will always look like line noise, but you will stop caring because this also make the concise code easier to read. K has since become my language of choice.“
Vektory lze zkonstruovat i na základě několika vestavěných algoritmů. Příkladem může být vektor obsahující sekvenci hodnot od 0 do zadaného limitu (kromě), tedy vzdálená obdoba generátoru range z Pythonu:
!10 0 1 2 3 4 5 6 7 8 9
Při potřebě začínat od hodnoty odlišné od nuly můžeme použít součet skaláru s vektorem:
1+!10 1 2 3 4 5 6 7 8 9 10
Vytvoření vektoru n zvolených hodnot:
10#0 0 0 0 0 0 0 0 0 0 0
Vytvoření vektoru z opakujících se hodnot:
10#1 2 3 1 2 3 1 2 3 1 2 3 1
Kombinace obou možností:
20#!4 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
Výběr tří libovolných hodnot od 0 do 10 (kromě):
3 _draw 10 2 7 8
Výběr deseti libovolných hodnot od 0 do 2 (kromě):
10 _draw 2 0 1 0 0 0 0 1 1 1 1
Zde můžeme získat prvky se stejnou hodnotou:
5 _draw 5 2 0 4 4 1
Zadáním záporného rozsahu zajistíme, že se prvky nebudou opakovat:
5 _draw -5 4 0 2 3 1
Matice 2×3:
2 3 _draw 6 (4 4 5 4 5 3) 2 3 _draw -6 (1 3 5 0 2 4)
Zamíchání 52 žolíkovými kartami s jejich rozdělením do čtyř hromádek po třinácti kartách:
4 13_draw-52 (31 29 21 12 20 10 4 15 39 2 38 49 27 17 25 18 5 11 9 3 28 41 35 48 26 13 8 22 19 40 51 44 0 33 24 43 6 7 46 42 50 45 1 32 16 23 34 36 30 37 14 47)
13. Převod hodnoty do zvolené číselné soustavy
Pravděpodobně unikátní operací, kterou je možné v jazyku K provést, je převod hodnoty do zvolené číselné soustavy, ovšem takovým způsobem že se vrátí vektor s jednotlivými ciframi. Podívejme se na příklady použití.
Převod do binární soustavy:
2_vs 255 1 1 1 1 1 1 1 1 2_vs 1000 1 1 1 1 1 0 1 0 0 0
Převod do šestnáctkové a dvanáctkové soustavy:
16_vs 255 15 15 12_vs 1000 6 11 4
Převod hodnot od 0 do 9 do dvojkové soustavy – vrátí se seznam seznamů (nikoli ovšem matice, protože každý řádek má odlišnou délku):
2_vs !10 (!0 ,1 1 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 1)
14. Vyhledávání hodnot ve vektorech
Programovací jazyk K nabízí programátorům hned několik operátorů určených pro vyhledávání prvků ve vektorech. Tyto operátory si postupně popíšeme; nejdříve si však necháme vytvořit desetiprvkový vektor s vyplněnými náhodnými hodnotami, s nímž budeme provádět všechny další operace:
x:10 _draw 10 x 9 6 9 3 3 0 4 5 4 7
Vyhledáme index prvního prvku s hodnotou 6 (indexuje se od nuly):
x?6 1
Vyhledáme nulový prvek:
x?0 5
Pokud vyhledávaný prvek neexistuje, vrátí se délka vektoru (což je index neexistujícího prvku). Tento drobný trik umožňuje zjednodušit některé algoritmy:
x?10 10 x?-1 10
Vyhledání unikátních hodnot ve vektoru – zde se použije monadická forma operátoru ?:
?x 9 6 3 0 4 5 7
Maska s prvky nastavenými na jedničku tam, kde prvek původního vektoru odpovídá zapsané podmínce:
9=x 1 0 1 0 0 0 0 0 0 0 6=x 0 1 0 0 0 0 0 0 0 0 x>5 1 1 1 0 0 0 0 0 0 1 x<5 0 0 0 1 1 1 1 0 1 0
Získání informací, kolikrát a na jaké pozici se prvek opakuje:
=x (0 2 ,1 3 4 ,5 6 8 ,7 ,9)
Příklad: 0 2 na prvním řádku seznamu znamená, že prvek se opakuje na 0 a 2 pozici (jeho hodnotu zjistíme indexováním).
Získání indexů prvků odpovídajících podmínce:
&x>5 0 1 2 9 &x<5 3 4 5 6 8
15. Další operace s vektory
Protože vektory (resp. přesněji řečeno seznamy, ovšem v praxi se typicky jedná hlavně o vektory) jsou základním složeným datovým typem programovacího jazyka K, existuje přímo v základní verzi tohoto jazyka (tj. bez nutnost použití externích knihoven) velké množství dalších funkcí a operátorů, které dokážou vektory zpracovat. Některé z těchto funkcí a operátorů si ukážeme v této kapitole.
Operace pro získání prvního a posledního prvku vektoru jsou založeny na operátorech *1 a *|1:
*1 2 3 1 *|1 2 3 3
Získat lze i vektor bez prvního resp. bez posledního prvku, a to konkrétně operátorem _, kterému se předá kladná či záporná hodnota:
1_1 2 3 2 3 -1_1 2 3 1 2
Nepatrně složitější příklady založené na tomto operátoru a konstruktoru vektoru:
1_!10 1 2 3 4 5 6 7 8 9 -1_!10 0 1 2 3 4 5 6 7 8
Vektor lze velmi snadno otočit s využitím monadické formy operátoru | (dyadická forma vyhledává maximum, což již dobře známe):
|x 7 4 5 4 0 3 3 9 6 9
I řetězec je vektorem (znaků), takže otočení řetězce je triviální:
|"foobarbaz" "zabraboof"
Podobným způsobem lze prvky vektoru rotovat o zadaný počet prvku (rotace doprava při kladném počtu):
1!x 6 9 3 3 0 4 5 4 7 9
Další operátor slouží pro získání těch prvků vektoru, které odpovídají binární masce (dalšímu vektoru). Jedná se vlastně o „paralelní“ implementaci filtru:
x[&x>5] 9 6 9 7 x[&x<5] 3 3 0 4 4
Mimochodem, vlastní selekce prvků pomocí [] je vlastně jen syntaktickým cukrem k operátoru @:
1 2 3@1 2
Poslední operátor se jmenuje where. Tento operátor vytvoří nový vektor, v němž se vždy index prvku z původního vektoru opakuje x-krát:
&x 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 3 3 3 4 4 4 6 6 6 6 7 7 7 7 7 8 8 8 8 9 9 9 9 9 9 9
16. Modifikátory over, scan a each
Programovací jazyk K však kromě poměrně rozsáhlé řady primitivních funkcí obsahuje, ostatně podobně jako již popsaný jazyk APL, několik modifikátorů, pomocí nichž jsou funkce aplikovány nikoli na jeden či dva parametry, ale postupně na celé vektory nebo matice. Díky modifikátorům (říká se jim i operátory, ovšem význam tohoto slova je odlišný od významu, který toto slovo má v jiných programovacích jazycích a proto ho nebudu používat) je možné eliminovat velké množství programových smyček a mnohdy tak například několikařádkovou proceduru zapsat pomocí jediného výrazu, což ostatně uvidíme i v několika demonstračních příkladech.
Modifikátor over zapisovaný znakem / postupně aplikuje zapsaný operátor na prvky vektoru, resp. na mezivýsledek a prvek vektoru. Odpovídá tak funkci vyššího řádu reduce. Kombinace +/ sečte všechny prvky vektoru:
+/1 2 3 6 +/!10 45
Naproti tomu modifikátor scan zapisovaný zpětným lomítkem vrací vektor se všemi vypočtenými mezivýsledky. Opět si ukažme kombinaci +\, jenž vrátí mezivýsledky postupného součtu prvků:
+\1 2 3 1 3 6 +\!10 0 1 3 6 10 15 21 28 36 45
Modifikátor each zapisovaný pomocí ' aplikuje programátorem zvolený operátor na všechny prvky vektoru a vrací nový vektor:
1+'!10 1 2 3 4 5 6 7 8 9 10
Aplikace operátoru + na dvojice prvků ze vstupního vektoru:
+':1 2 3 4 5 3 5 7 9
Takto se například vypočítá faktoriál deseti:
*/1+!10 3628800
Opět poněkud umělý příklad na vyhledání největšího a nejmenšího prvku:
x:10_draw 10 x 2 7 8 0 8 0 0 1 1 5 |/x 8 &/x 0
Malý trik na výpočet délky odvěsny pravoúhlého trojúhelníka:
_sqrt+/_sqr 3 4 5.0
17. Funkce
Poslední vlastností programovacího jazyka K, s níž se dnes setkáme, je deklarace uživatelských funkcí. Začneme tvorbou funkcí s jediným parametrem (a pochopitelně i jedinou výstupní hodnotou – více jich ostatně není díky existenci seznamů a vektorů zapotřebí). Tělo funkce se zapisuje do složených závorek, přičemž v těle funkce je možné použít symbol x reprezentující hodnotu parametru předaného do volání funkce. Taková funkce není pojmenovaná (je tedy anonymní) a voláme ji stejně, jako vestavěný monadický operátor.
Příkladem může být funkce vracející hodnotu parametru zvýšenou o jedničku:
{1+x}10 11 {1+x}10 20 30 11 21 31
Anonymní funkce pro výpočet faktoriálu:
{*/ 1+ !x} 5 120
Mezery jsou přebytečné, takže:
{*/1+!x}5 120
Funkce je plnohodnotnou hodnotou, takže ji můžeme uložit do proměnné a tím pádem ji pojmenovat:
fact:{*/1+!x} fact 10 3628800
Připomeňme si existenci modifikátoru ' (each). Lze ho použít i s naší funkcí:
fact' !10 1 1 2 6 24 120 720 5040 40320 362880
Funkce se dvěma parametry se již zapisuje nepatrně složitějším způsobem:
plus:{[x;y]x+y} plus[1;2] 3
Podívejme se ještě na zápis funkce pro seřazení prvků ve vektoru:
{x@<x}3 2 1 4 1 2 3 4
18. Náhrada programových smyček pomocí modifikátorů
Ve této kapitole si pro ilustraci použití výše zmíněného modifikátoru / v praxi ukážeme příklad převzatý z elektronické knihy „J for C Programmers“, ve kterém je předvedeno, jakým způsobem je možné pomocí modifikátoru / nalézt největší prvek v matici (mimochodem: zmíněná elektronická kniha je obsažena přímo v instalaci vývojového prostředí programovacího jazyka J). Příklad byl pochopitelně upraven takovým způsobem, aby ho bylo možné spustit v jazyku K (kde je paradoxně ještě kratší, než v případě už tak „zhuštěného“ jazyka J). Nejprve si uveďme odpovídající céčkový program, který nalezne prvek s maximální hodnotou v (dvourozměrné) matici x, jejíž rozměry jsou uloženy v konstantách xsize0 a xsize1:
int i, j; float maxval = x[0][0]; for (i = 0; i<=xsize0; ++i) { for (j = 0; j<=xsize1; ++j) { if (x[i][j] > maxval) { maxval = x[i][j]; } } }
V programovacím jazyku K je možné maximální prvek v matici nalézt dvojí aplikací modifikátoru / zkombinovaného s operátorem | (tento operátor, jak již víme, provádí výběr větší hodnoty z dvojice předaných parametrů, tj. jak skalárních hodnot, tak i vektorů popř. matic). První aplikace modifikátoru / slouží k výběru těch prvků na jednotlivých řádcích matice, které mají největší hodnotu, druhá aplikace pak již z tohoto mezivýsledku (tj. vektoru) vybere přímo maximální hodnotu, takže se celá sekvence zanořených smyček a podmíněného příkazu v programovacím jazyku K zmenší na jediný výraz, jehož délka je pouze čtyři znaky! Ve skutečnosti je však možné podmíněný příkaz eliminovat i v céčkovém programu, stačí ho nahradit například voláním makra MAX. Navíc si nikde nemusíme pamatovat rozměry pole (matice), neboť ty lze kdykoli za běhu programu zjistit z matice samotné:
m:(1 2 3 4 5 6 7 8 9) m (1 2 3 4 5 6 7 8 9) |/|/m 9
Příklad s náhodnými hodnotami:
m:10 10 _draw 999 m (273 779 884 97 859 19 21 122 104 500 820 919 746 480 172 929 838 345 294 20 306 256 697 866 662 792 472 961 527 214 315 541 960 891 220 767 918 359 786 703 843 793 871 538 446 457 365 580 998 309 837 773 469 245 843 69 817 492 590 48 931 93 559 366 177 460 731 137 998 216 607 86 163 488 480 7 667 935 606 844 131 365 974 655 752 179 320 326 394 695 345 899 907 399 550 448 204 718 432 260) |/m 931 919 974 891 859 929 918 961 998 844 |/|/m 998
19. Obsah druhé části článku
Ve druhé a současně i závěrečné části článku o neobvyklém programovacím jazyku K si popíšeme způsob práce s maticemi, protože právě při zpracování matic je možné využít zbývající standardní operátory, které jsou v jazyku implementovány (a to bez nutnosti používání knihoven).
20. Odkazy na Internetu
- 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