Hlavní navigace

Programovací jazyk K: důkaz, že mezi námi žijí mimozemšťané

21. 7. 2022
Doba čtení: 34 minut

Sdílet

 Autor: Depositphotos
Dnes se ve stručnosti seznámíme s programovacím jazykem K. Programy zapsané v tomto jazyce jsou velmi hutné (doslova několik znaků), ovšem mají podobu šumu na lince nebo zprávy poslané mimozemšťany.

Obsah

1. Programovací jazyk K – důkaz, že mezi námi žijí mimozemšťané

2. Stručná historie jazyka K

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

9. Seznamy a vektory

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

15. Další operace s vektory

16. Modifikátory over, scaneach

17. Funkce

18. Náhrada programových smyček pomocí modifikátorů

19. Obsah druhé části článku

20. Odkazy na Internetu

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
Poznámka: mimochodem – původní myšlenka na hutný a tím pádem i krátký kód, která vznikla v souvislosti s APL, je velmi dobrá. Pokud máme například k dispozici obecný modifikátor pro kombinaci libovolného binárního (dyadického) operátoru a řekněme vektorového součinu, je už samotný zápis výrazu využívajícího tuto kombinaci dostatečně idiomatický, že již není zapotřebí mnoha slov pro jeho vysvětlení a není nutné ho ani testovat – ostatně stejně tak není nutné testovat, zda pracuje správně například operátor +. Ovšem právě díky možnosti kombinace dvou či více operátorů a navíc aplikace těchto operátorů na vektory a matice vzniká kód, který skutečně vypadá jako zpráva poslaná mimozemšťany.

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.

Poznámka: z toho plyne, že všechny operátory mají shodnou prioritu.

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)
Poznámka: samotná výzva (prompt) není, na rozdíl od mnoha dalších variant interaktivní smyčky REPL, představována nějakým speciálním znakem. Poznáme ji pouze podle toho, že se kurzor nachází na třetím sloupci, nikoli na sloupci prvním.

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
Poznámka: jedná se o velmi elegantní způsob, jak operátory | a & použít nejenom v „céčkovském“ významu, ale i v obecnějším pojetí.

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"
Poznámka: to znamená, že mnoho operátorů a funkcí popsaných níže lze aplikovat i na řetězce.

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
Poznámka: tato operace více vynikne ve chvíli, kdy se bude pracovat s proměnnými a nikoli pouze přímo s hodnotami.

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
Poznámka: povšimněte si, že operátor má nižší prioritu než „konstruktor vektoru“.

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
Poznámka: přiřazení je jedna z mála operací, která nevypisuje svůj výsledek na terminál. Pokud si přejeme vypsat hodnotu přiřazenou do proměnné, je nutné zapsat dvojtečku i na začátek celého výrazu:
  :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
Poznámka: opět platí, že prakticky všechny mezery jsou ignorovány a nemají pro interpret programovacího jazyka K žádný význam. Stejně dobře tedy můžeme psát:
  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
Poznámka: jedná se snad o jediný syntaktický cukr, který v jazyku K nalezneme.

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, scaneach

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
Poznámka: předchozí příklad je poněkud umělý, protože můžeme použít i jednodušší a kratší 1+!10.

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
Poznámka: některé sofistikovanější funkce si uvedeme příště.

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é:

root_podpora

  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

  1. K language – an introduction
    http://www.math.bas.bg/ban­tchev/place/k.html
  2. K7 Tutorial
    https://cs.nyu.edu/~shasha/pa­pers/tutorial
  3. An Interview with Arthur Whitney, Kx CEO and Developer of Kx Technology, January 4, 2004
    https://web.archive.org/web/20150813004101/htt­p://kx.com/arthur-interview.php
  4. A Shallow Introduction to the K Programming Language
    https://web.archive.org/web/20130801233812/htt­p://www.kuro5hin.org/story/2002/11/14/22741/791
  5. A Conversation with Arthur Whitney
    https://queue.acm.org/deta­il.cfm?id=1531242
  6. Anecdote about Arthur Whitney
    https://news.ycombinator.com/i­tem?id=13590065
  7. K – list of idioms
    https://github.com/kevinlaw­ler/kona/wiki/Idioms
  8. Appendix A. Incunabulum
    http://keiapl.org/rhui/re­member.htm#incunabulum
  9. K code study
    https://docs.google.com/do­cument/d/1W83ME5JecI2hd5hA­UqQ1BVF32wtCel8zxb7WPq-D4f8/edit
  10. K tutorial
    https://github.com/kevinlaw­ler/kona/wiki/Tutorial
  11. K by EXAMPLE
    http://vrabi.web.elte.hu/k/kbyeg.k
  12. BQN: An APL Variant from Marshall Lochbaum (mlochbaum.github.io)
    https://news.ycombinator.com/i­tem?id=24167804
  13. Raytracer in 7 lines in K
    http://www.nsl.com/k/ray/ray.k
  14. Marshall Lochbaum
    https://www.aplwiki.com/wi­ki/Marshall_Lochbaum
  15. BQN
    https://www.aplwiki.com/wiki/BQN
  16. Co-dfns
    https://www.aplwiki.com/wiki/Co-dfns
  17. Array model
    https://www.aplwiki.com/wi­ki/Array_model#Based_arra­y_theory
  18. Fonts for BQN
    https://mlochbaum.github.i­o/BQN/fonts.html
  19. Leading axis theory
    https://www.aplwiki.com/wi­ki/Leading_axis_theory
  20. A based system for general arrays
    https://dl.acm.org/doi/ab­s/10.1145/586656.586663
  21. APL – A Glimpse of Heaven (2006)
    https://news.ycombinator.com/i­tem?id=19325361
  22. APL and J
    https://crypto.stanford.e­du/~blynn/c/apl.html
  23. ivy (dokumentace)
    https://pkg.go.dev/robpike­.io/ivy#section-readme
  24. ivy na GitHubu
    https://github.com/robpike/ivy/
  25. Ivy na APL wiki
    https://aplwiki.com/wiki/Ivy
  26. Implementing a bignum calculator (slajdy)
    https://talks.godoc.org/git­hub.com/robpike/ivy/talks/i­vy.slide#1
  27. Implementing a bignum calculator – Rob Pike – golang-syd November 2014
    https://www.youtube.com/wat­ch?v=PXoG0WX0r_E
  28. Rob Pike na Wikipedii
    https://en.wikipedia.org/wi­ki/Rob_Pike
  29. Rob Pike na cat-v
    http://genius.cat-v.org/rob-pike/
  30. 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/
  31. Programovací technika nazvaná tacit programming
    https://www.root.cz/clanky/pro­gramovaci-technika-nazvana-tacit-programming/
  32. Oslava 55 let od vzniku první implementace jazyka APL
    https://www.root.cz/clanky/oslava-55-let-od-vzniku-prvni-implementace-programovaciho-jazyka-apl/
  33. NuVoc
    https://code.jsoftware.com/wiki/NuVoc
  34. J (programming language) [Wikipedia]
    https://en.wikipedia.org/wi­ki/J_%28programming_langu­age%29
  35. J – Absolutely Essential Terms
    https://code.jsoftware.com/wi­ki/Vocabulary/AET
  36. J – Atoms and Arrays
    https://code.jsoftware.com/wi­ki/Vocabulary/Nouns#Atom
  37. Why J
    https://www.jsoftware.com/hel­p/primer/why_j.htm
  38. What is an Array?
    https://vector.org.uk/what-is-an-array/
  39. Comments
    http://www.gavilan.edu/csis/lan­guages/comments.html
  40. Vector (Wolfram MathWorld)
    https://mathworld.wolfram­.com/Vector.html
  41. n-Tuple (Wolfram MathWorld)
    https://mathworld.wolfram.com/n-Tuple.html
  42. n-Vector (Wolfram MathWorld)
    https://mathworld.wolfram.com/n-Vector.html
  43. Matrix (Wolfram MathWorld)
    https://mathworld.wolfram­.com/Matrix.html
  44. Array (Wolfram MathWorld)
    https://mathworld.wolfram­.com/Array.html
  45. ND Arrays (Tensors) in different languages
    https://www.youtube.com/wat­ch?v=WbpbEilgQBc
  46. Extending APL to Infinity\
    https://www.jsoftware.com/pa­pers/eem/infinity.htm
  47. Vector Library (R7RS-compatible)
    https://srfi.schemers.org/srfi-133/srfi-133.html
  48. Vectors (pro Gauche)
    https://practical-scheme.net/gauche/man/gauche-refe/Vectors.html
  49. Kawa: Compiling Scheme to Java
    https://www.mit.edu/afs.new/sip­b/project/kawa/doc/kawa-tour.html
  50. Kawa in Languages shootout
    http://per.bothner.com/blog/2010/Kawa-in-shootout/
  51. Kawa 2.0 Supports Scheme R7RS
    https://developers.slashdot­.org/story/14/12/13/2259225/ka­wa-20-supports-scheme-r7rs/
  52. Kawa — fast scripting on the Java platform
    https://lwn.net/Articles/623349/
  53. Incanter is a Clojure-based, R-like platform for statistical computing and graphics.
    http://incanter.org/
  54. Evolution of incanter (Gource Visualization)
    https://www.youtube.com/wat­ch?v=TVfL5nPELr4
  55. Questions tagged [incanter] (na Stack Overflow)
    https://stackoverflow.com/qu­estions/tagged/incanter?sor­t=active
  56. Data Sorcery with Clojure
    https://data-sorcery.org/contents/
  57. Back to the Future: Lisp as a Base for a Statistical Computing System
    https://rd.springer.com/chap­ter/10.1007/978–3–7908–2084–3_2
  58. Incanter Cheat Sheet
    http://incanter.org/docs/incanter-cheat-sheet.pdf
  59. Back to the Future: Lisp as a Base for a Statistical Computing System (celá verze článku)
    https://www.researchgate.net/pu­blication/227019917_Back_to_the_Fu­ture_Lisp_as_a_Base_for_a_Sta­tistical_Computing_System
  60. BQN: finally, an APL for your flying saucer
    https://mlochbaum.github.io/BQN/
  61. Is BQN stable?
    https://mlochbaum.github.i­o/BQN/commentary/stability­.html
  62. Specification: BQN system-provided values
    https://mlochbaum.github.i­o/BQN/spec/system.html
  63. Tutorial: BQN expressions
    https://mlochbaum.github.i­o/BQN/tutorial/expression­.html
  64. BQN primitives
    https://mlochbaum.github.i­o/BQN/doc/primitive.html
  65. Function trains
    https://mlochbaum.github.i­o/BQN/doc/train.html
  66. BQN community links
    https://mlochbaum.github.i­o/BQN/community/index.html
  67. BQN UV
    https://observablehq.com/@lsh/bqn-uv
  68. APL Wiki
    https://aplwiki.com/wiki/
  69. The Array Cast
    https://www.arraycast.com/e­pisodes/episode-03-what-is-an-array
  70. EnthusiastiCon 2019 – An Introduction to APL
    https://www.youtube.com/wat­ch?v=UltnvW83_CQ
  71. Dyalog
    https://www.dyalog.com/
  72. Try APL!
    https://tryapl.org/
  73. Lisp-Stat Information
    http://homepage.cs.uiowa.e­du/~luke/xls/xlsinfo/
  74. Sample Plots in Incanter
    https://github.com/incanter/in­canter/wiki/Sample-Plots-in-Incanter#line
  75. vectorz-clj
    https://github.com/mikera/vectorz-clj
  76. vectorz – Examples
    https://github.com/mikera/vectorz-clj/wiki/Examples
  77. 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
  78. Vectors and matrices in Julia
    https://fncbook.github.io/v1­.0/linsys/demos/matrices-julia.html
  79. Array vs Matrix in R Programming
    https://www.geeksforgeeks.org/array-vs-matrix-in-r-programming/
  80. Concurrency (computer science)
    https://en.wikipedia.org/wi­ki/Category:Concurrency_%28com­puter_science%29
  81. Koprogram
    https://cs.wikipedia.org/wi­ki/Koprogram
  82. Coroutine
    https://en.wikipedia.org/wi­ki/Coroutine
  83. Coroutines in C
    http://www.chiark.greenen­d.org.uk/~sgtatham/corouti­nes.html
  84. S-expression (Wikipedia)
    https://en.wikipedia.org/wiki/S-expression
  85. S-Expressions (Rosetta Code)
    http://rosettacode.org/wiki/S-Expressions
  86. Introducing Julia/Metaprogramming
    https://en.wikibooks.org/wi­ki/Introducing_Julia/Meta­programming
  87. Tutorial for the Common Lisp Loop Macro
    http://www.ai.sri.com/pkarp/loop.html
  88. 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
  89. Clojure Macro Tutorial (Part II: The Compiler Strikes Back)
    http://www.learningclojure­.com/2010/09/clojure-macro-tutorial-part-ii-compiler.html
  90. Clojure Macro Tutorial (Part III: Syntax Quote)
    http://www.learningclojure­.com/2010/09/clojure-macro-tutorial-part-ii-syntax.html
  91. Clojure Macros and Metaprogramming
    http://clojure-doc.org/articles/language/macros.html
  92. Fatvat – Exploring functional programming: Clojure Macros
    http://www.fatvat.co.uk/2009/02/clo­jure-macros.html
  93. CS 2101 Parallel Computing with Julia
    https://www.coursehero.com/fi­le/11508091/CS-2101-Parallel-Computing-with-Julia/
  94. Julia By Example
    https://samuelcolvin.github­.io/JuliaByExample/
  95. Array Programming
    https://en.wikipedia.org/wi­ki/Array_programming
  96. Discovering Array Languages
    http://archive.vector.org­.uk/art10008110
  97. no stinking loops – Kalothi
    http://www.nsl.com/
  98. Vector (obsahuje odkazy na články, knihy a blogy o programovacích jazycích APL, J a K)
    http://www.vector.org.uk/
  99. APL Interpreters
    http://www.vector.org.uk/?a­rea=interpreters
  100. APL_(programming_language
    http://en.wikipedia.org/wi­ki/APL_(programming_langu­age
  101. APL FAQ
    http://www.faqs.org/faqs/apl-faq/
  102. APL FAQ (nejnovější verze)
    http://home.earthlink.net/~swsir­lin/apl.faq.html
  103. A+
    http://www.aplusdev.org/
  104. APLX
    http://www.microapl.co.uk/
  105. FreeAPL
    http://www.pyr.fi/apl/index.htm
  106. Learning J (Roger Stokes)
    http://www.jsoftware.com/hel­p/learning/contents.htm
  107. J: a modern, high-level, general-purpose, high-performance programming language
    http://www.jsoftware.com/
  108. K, Kdb: an APL derivative for Solaris, Linux, Windows
    http://www.kx.com
  109. openAPL (GPL)
    http://sourceforge.net/pro­jects/openapl
  110. Parrot APL (GPL)
    http://www.parrotcode.org/
  111. Learning J (Roger Stokes)
    http://www.jsoftware.com/hel­p/learning/contents.htm
  112. Rosetta Code
    http://rosettacode.org/wiki/Main_Page
  113. Why APL
    http://www.acm.org/sigapl/whyapl.htm
  114. Introducing Julia/Functions
    https://en.wikibooks.org/wi­ki/Introducing_Julia/Functi­ons
  115. Functions (Julia documentation)
    https://docs.julialang.or­g/en/v1/manual/functions/
  116. Evaluate binomial coefficients
    http://rosettacode.org/wi­ki/Evaluate_binomial_coef­ficients
  117. Ackermann function
    http://rosettacode.org/wi­ki/Ackermann_function
  118. Julia (front page)
    http://julialang.org/
  119. Julia – dokumentace
    http://docs.julialang.org/
  120. Julia – repositář na GitHubu
    https://github.com/JuliaLang/julia
  121. Julia (programming language)
    https://en.wikipedia.org/wi­ki/Julia_%28programming_lan­guage%29
  122. IJulia
    https://github.com/JuliaLan­g/IJulia.jl
  123. Introducing Julia
    https://en.wikibooks.org/wi­ki/Introducing_Julia
  124. Julia: the REPL
    https://en.wikibooks.org/wi­ki/Introducing_Julia/The_REPL
  125. Month of Julia
    https://github.com/DataWo­okie/MonthOfJulia
  126. Learn X in Y minutes (where X=Julia)
    https://learnxinyminutes.com/doc­s/julia/
  127. New Julia language seeks to be the C for scientists
    http://www.infoworld.com/ar­ticle/2616709/application-development/new-julia-language-seeks-to-be-the-c-for-scientists.html
  128. Julia: A Fast Dynamic Language for Technical Computing
    http://karpinski.org/publi­cations/2012/julia-a-fast-dynamic-language
  129. The LLVM Compiler Infrastructure
    http://llvm.org/
  130. Julia: benchmarks
    http://julialang.org/benchmarks/
  131. Type system
    https://en.wikipedia.org/wi­ki/Type_system
  132. Half-precision floating-point format
    https://en.wikipedia.org/wiki/Half-precision_floating-point_format
  133. Dartmouth BASIC
    https://en.wikipedia.org/wi­ki/Dartmouth_BASIC
  134. BASIC 4th Edition
    http://www.bitsavers.org/pdf/dar­tmouth/BASIC_4th_Edition_Jan68­.pdf
  135. VECTRAN
    https://encyclopedia2.the­freedictionary.com/VECTRAN
  136. Comparison of programming languages (array)
    https://en.wikipedia.org/wi­ki/Comparison_of_programmin­g_languages_(array)
  137. BASIC at 50
    https://www.dartmouth.edu/ba­sicfifty/commands.html
  138. BBC Basic – arrays
    http://www.riscos.com/sup­port/developers/bbcbasic/par­t2/arrays.html
  139. Datová struktura
    https://cs.wikipedia.org/wi­ki/Datov%C3%A1_struktura
  140. SIMD instrukce využívané v moderních mikroprocesorech řady x86
    https://www.root.cz/clanky/simd-instrukce-vyuzivane-v-modernich-mikroprocesorech-rady-x86/
  141. 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/
  142. 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/
  143. Inductive type
    https://en.wikipedia.org/wi­ki/Inductive_type
  144. JuliaMono, a font for programming
    https://github.com/cormulli­on/juliamono
  145. It’s arrays all the way down
    https://xpqz.github.io/le­arnapl/array.html

Byl pro vás článek přínosný?