Hlavní navigace

Programovací jazyk J: operátory, uživatelské funkce a tacit programming

26. 1. 2010
Doba čtení: 15 minut

Sdílet

V patnácté části našeho seriálu o historii výpočetní techniky společně dokončíme popis programovacího jazyka J. Budeme se zabývat především použitím operátorů a následně způsobem tvorby monadických i dyadických uživatelských funkcí. Taktéž si v článku vysvětlíme význam termínu tacit programming.

Obsah

1. Operátor / (reduce)

2. Náhrada programových smyček pomocí operátorů

3. Dyadická forma operátoru /

4. Operátor \

5. Tvorba uživatelských funkcí

6. Monadické uživatelské funkce

7. Dyadické uživatelské funkce

8. Tacit programming

9. Literatura

10. Odkazy na Internetu

1. Operátor / (reduce)

V předchozích dvou částech seriálu o programovacím jazyku J jsme se seznámili se základními (primitivními) funkcemi tohoto jazyka, které představují základní stavební kameny všech vytvářených aplikací. Programovací jazyk J však kromě poměrně rozsáhlé řady primitivních funkcí obsahuje, podobně jako již popsaný jazyk APL, několik operátorů, pomocí nichž jsou funkce aplikovány nikoli na jeden či dva parametry, ale postupně na celé vektory nebo matice. Díky operátorům (význam tohoto slova je odlišný od významu, který toto slovo má v jiných jazycích) 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 (viz druhou kapitolu). Jedním z nejdůležitějších operátorů jazyka J je operátor /, který jsme si již v jednodušší podobě představili při popisu jazyka APL. Tento operátor, který se zapisuje za identifikátor primitivní či uživatelské funkce, postupně danou funkci aplikuje na první dva prvky argumentu, dále ji aplikuje na průběžný výsledek a třetí prvek atd., do doby, než jsou všechny prvky argumentu zpracovány (jinými slovy – daná dyadická funkce je jakoby zapsána mezi všechny prvky předané datové struktury, počet operací je roven n-1 v případě, že předaný vektor má počet prvků n):

   NB. Součet všech čísel v řadě od 1 do 10.
   + / 1 2 3 4 5 6 7 8 9 10
55

   NB. Vektor hodnot můžeme vytvořit
   NB. taktéž s využitím generátoru
   NB. indexů (viz předchozí části
   NB. seriálu). Ovšem pozor - indexy
   NB. se generují od 0, nikoli od 1.
   + / i. 10
45

   NB. Zde se již vektor skutečně vygeneruje
   NB. tak, že jeho první prvek má
   NB. jedničkovou hodnotu.
   + / 1 + i. 10
55

Operátor / je však samozřejmě možné použít i v kombinaci s libovolnou dyadickou funkcí – může se jednat jak o aritmetické funkce, tak i o funkce logické (booleovské), porovnávací (relační), maticové aj. Následují příklady použití některých těchto funkcí; nejprve funkcí booleovských aplikovaných na vektory binárních hodnot:

   NB. Použití booleovské funkce "or"
   NB. (logický součet)
   +./ 0 0 0 0

   +./ 0 0 0 1
1
   +./ 1 1 1 1
1

   NB. Použití booleovské funkce "and"
   NB. (logický součin)
   *./ 0 0 0 0

   *./ 0 0 0 1

   *./ 1 1 1 1
1

   NB. Použití booleovské funkce ekvivalence
   =/ 0 0 0 0
1
   =/ 0 0 0 1

   =/ 1 1 1 1
1

   NB. Použití booleovské funkce "xor"
   NB. (nonekvivalence)
   ~:/ 0 0 0 0

   ~:/ 0 0 0 1
1
   ~:/ 1 1 1 1

Mezi další dyadické funkce, které lze zkombinovat s operátorem /, patří například funkce pro výpočet (zjištění) minima, maxima, součinu (zde korespondujících prvků vektorů) a mocniny o zvoleném základu:

   NB. Výběr nejmenšího prvku z vektoru.
   <. / 5 4 67 2 1 42 3 7 6
1

   NB. Výběr největšího prvku z vektoru.
   >. / 5 4 67 2 1 42 3 7 6
67

   NB. Jeden ze způsobů výpočtu skalárního
   NB. součinu dvou vektorů.
   +/ (1 2 3) * (1 2 3)
14

   NB. Skalární součin dvou na sebe kolmých
   NB. vektorů je vždy nulový.
   +/ (1 0 0) * (0 1 0)


   NB. Výpočet prvních deseti mocnin
   NB. základu 2 (včetně 2^0).
   2 ^ i. 10
1 2 4 8 16 32 64 128 256 512

   NB. Suma prvních deseti mocnin
   NB. základu 2. Výsledek by měl
   NB. být roven: (2^(n+1))-1
   + / 2 ^ i. 10
1023

   NB. Výpočet známé úlohy se šachovnicí a semínky
   NB. kladenými na jednotlivá políčka šachovnice.
   2 ^ i. 64
1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192
16384 32768 65536 131072 262144 524288 1.04858e6
2.09715e6 4.1943e6 8.38861e6 1.67772e7 3.35544e7
6.71089e7 1.34218e8 2.68435e8 5.36871e8 1.07374e9
2.14748e9 4.29497e9 8.58993e9 1.71799e10 3.43597e10 6.87195...

   NB. Celkový počet všech semínek na šachovnici.
   + / 2 ^ i. 64
1.84467e19

2. Náhrada programových smyček pomocí operátorů

Ve druhé kapitole si pro ilustraci použití operá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í operátoru / nalézt největší prvek v matici (zmíněná elektronická kniha je obsažena přímo v instalaci vývojového prostředí programovací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&jt;=xsize0; ++i)
{
    for (j = 0; j<=xsize1; ++j)
    {
        if (x[i][j] > maxval)
        {
            maxval = x[i][j];
        }
    }
}

V programovacím jazyku J lze maximální prvek v matici nalézt dvojí aplikací operátoru / zkombinovaného s funkcí >. (ta 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 operá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 J zmenší na jediný výraz. 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, což však již není možné v příkladu uvedeném níže. Navíc si nikde nemusíme pamatovat rozměry pole (matice), neboť ty lze kdykoli za běhu programu zjistit:

   NB. Nejprve si vytvoříme matici
   NB. s testovacími daty.
   matice =: 3 3 $ _4 + i.9
   matice
_4 _3 _2
_1  0  1
 2  3  4

   NB. Nalezneme největší prvek v matici
   NB. dvojím použitím operátoru /
   (<./) <./ matice
4

Druhý příklad je již poněkud složitější – nalezení sloupce, ve kterém se nachází prvek s maximální hodnotou –, ale při použití programovacího jazyka J se opět obejdeme bez nutnosti použití programových smyček a podmínek. Sloupec, ve kterém se prvek s největší hodnotou v matici nachází, lze zjistit s využitím dyadické funkce i. (index of), která vrací index prvního prvku obsahujícího danou hodnotu (prvním parametrem této funkce je většinou vektor, druhým parametrem hledaná hodnota). Povšimněte si především použití závorek, které eliminují nutnost dvojího použití mezivýsledku >./ matice v zapisovaném výrazu (viz též osmá kapitola, v níž se tímto tématem budeme zabývat podrobněji):

(i. >./) >./ matice

Céčkovský ekvivalent je stále mnohonásobně delší kvůli nutnosti použití programových smyček a podmínek:

int i, j, maxcol = 0;
float maxval = x[0][0];
for (i = 0; i&jt;=xsize0; ++i)
{
    for (j = 0; j<=xsize1; ++j)
    {
        if (x[i][j] > maxval)
        {
            maxval = x[i][j];
            maxcol = j
        }
    }
}

3. Dyadická forma operátoru /

Při popisu programovacího jazyka APL jsme se mj. zmínili i o operátoru „outer product“ zapisovaného dvojicí symbolů ◦. (kolečko+tečka) za nimiž následovalo jméno či symbol nějaké primitivní funkce popř. identifikátor uživatelské dyadické funkce. Tento operátor je založen na principu aplikace zvolené dyadické funkce na dvojici vektorů x a y, přičemž vybraná funkce je aplikována na všechny možné kombinace složek prvního a druhého vektoru. Výsledkem je matice Z obsahující v prvku zij návratovou hodnotu funkce aplikované na prvky xi a yj. Význam tohoto operátoru jsme si vysvětlili na příkladu, ve kterém se vytvořila a následně vypsala část tabulky malé násobilky (pozor – následující úryvek kódu je zapsaný v syntaxi odpovídající programovacímu jazyku APL, nikoli J):

     1 2 3 4 5 ◦.× 1 2 3 4 5
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25

Programovací jazyk J sice neobsahuje specializovaný operátor typu ◦., ale ani to vlastně není zapotřebí, protože rozšiřuje možnosti operátoru / popsaného v první a druhé kapitole. Zatímco v APL byl operátor / (reduce) pouze monadický (bylo ho možné použít s parametrem zapisovaným napravo od identifikátoru funkce), je možné v programovacím jazyce J využít i jeho dyadickou formu, při níž se první parametr (vektor) zapisuje nalevo od operátoru+funkce a druhý parametr (většinou taktéž vektor) napravo. Výsledek aplikace „dyadického“ operátoru / (nazývaného poněkud neobvykle table) je v tomto případě stejný, jako při použití operátoru ◦. v programovacím jazyce APL (u některých funkcí použitých spolu s tímto operátorem dochází k několika malým změnám chování, které však nejsou v naprosté většině případů podstatné).

Výše uvedený příklad by se tedy dal přepsat do programovacího jazyka J dvěma způsoby: přímým zápisem dvojic vektorů, na něž by se aplikoval operátor „/“ v kombinaci s funkcí násobení, nebo využitím generátoru indexů pro zkonstruování obou vektorů. Ve druhém případě opět nesmíme zapomenout na to, že se indexy generují od nuly a nikoli od jedničky:

   NB. Tabulka malé násobilky vzniklá
   NB. aplikací operátoru "outer product"
   NB. na dvojici explicitně zapsaných vektorů
   1 2 3 4 5 */ 1 2 3 4 5
1  2  3  4  5
2  4  6  8 10
3  6  9 12 15
4  8 12 16 20
5 10 15 20 25

   NB. Použití generátoru indexů pro výpočet
   NB. tabulky malé násobilky.
   (1+i.5) */ (1+i.5)
1  2  3  4  5
2  4  6  8 10
3  6  9 12 15
4  8 12 16 20
5 10 15 20 25

S využitím operátoru outer product je možné zkonstruovat velké množství matic se speciálními vlastnostmi; tyto matice mohou mít samozřejmě téměř libovolnou velikost. Jedná se například o jednotkové matice (obsahují jedničky v diagonále, ostatní prvky jsou nulové), trojúhelníkové matice různého typu (jedničky se nachází pod či nad diagonálou, ostatní prvky jsou nulové) atd. Tvorba těchto matic je ilustrována na následujících příkladech, ve kterých se často používají porovnávací (relační) funkce:

   NB. Pomocný vektor obsahující číselnou
   NB. řadu 0 1 2 3 4 5
   vect =. i. 5

   NB. Matice obsahující prvky se shodnými
   NB. hodnotami na vedlejších diagonálách.
   vect +/ vect
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8

   NB. Jednotková matice.
   vect =/ vect
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1

   NB. Inverze všech prvků jednotkové
   NB. matice.
   vect ~:/ vect
0 1 1 1 1
1 0 1 1 1
1 1 0 1 1
1 1 1 0 1
1 1 1 1 0

   NB. Rotace jednotkové matice
   |. vect =/ vect
0 0 0 0 1
0 0 0 1 0
0 0 1 0 0
0 1 0 0 0
1 0 0 0 0

   NB. Matice obsahující NAD hlavní
   NB. diagonálou jednotkové prvky.
   vect </ vect
0 1 1 1 1
0 0 1 1 1
0 0 0 1 1
0 0 0 0 1
0 0 0 0 0

   NB. Matice obsahující NAD hlavní
   NB. diagonálou (včetně diagonály)
   NB. jednotkové prvky.
   vect </ vect
1 1 1 1 1
0 1 1 1 1
0 0 1 1 1
0 0 0 1 1
0 0 0 0 1

   NB. Matice obsahující POD hlavní
   NB. diagonálou (včetně diagonály)
   NB. jednotkové prvky.
   vect >:/ vect
1 0 0 0 0
1 1 0 0 0
1 1 1 0 0
1 1 1 1 0
1 1 1 1 1

   NB. Na hlavní diagonále je
   NB. číselná posloupnost začínající
   NB. nulou, ostatní prvky jsou nulové
   vect * vect =/ vect
0 0 0 0 0
0 1 0 0 0
0 0 2 0 0
0 0 0 3 0
0 0 0 0 4

   NB. Na hlavní diagonále je
   NB. číselná posloupnost začínající
   NB. jedničkou, ostatní prvky jsou nulové
   (vect+1) * vect =/ vect
1 0 0 0 0
0 2 0 0 0
0 0 3 0 0
0 0 0 4 0
0 0 0 0 5

   NB. Rotace předchozí matice
   |. (vect+1) * vect =/ vect
0 0 0 0 5
0 0 0 4 0
0 0 3 0 0
0 2 0 0 0
1 0 0 0 0

Příklad použití operátoru / s nekomutativní funkcí:

   (i.5) ^/ (i.5)
   1 0  0  0   0
   1 1  1  1   1
   1 2  4  8  16
   1 3  9 27  81
   1 4 16 64 256

Kdo dává přednost transponované tabulce (mocniny rostou po jednotlivých řádcích, základ po sloupcích), může použít funkci |: aplikovanou na vypočtenou matici. I v tomto případě totiž platí, že jsou funkce vyčíslovány zprava doleva, nejdříve je tedy vypočtena matice 5×5 hodnot, která je až následně transponována:

   |: (i.5) ^/ (i.5)
   1 1  1  1   1
   0 1  2  3   4
   0 1  4  9  16
   0 1  8 27  64
   0 1 16 81 256

   NB. Kratší zápis pro ty, co šetří
   NB. každý stisk klávesy :-)
   |:(i.5)^/i.5
   1 1  1  1   1
   0 1  2  3   4
   0 1  4  9  16
   0 1  8 27  64
   0 1 16 81 256

4. Operátor \

Druhým operátorem, který si v dnešním článku popíšeme, je operátor \. Tento operátor zpracovává data podobným způsobem, jako výše popsaný operátor /, ovšem s tím rozdílem, že vrací posloupnost obsahující všechny mezivýsledky postupné aplikace dané funkce na vstupní parametr, například vektor (chování tohoto operátoru je tedy odlišné od stejně označeného operátoru známého z programovacího jazyka APL). Na následujícím příkladu si povšimněte, že interpret programovacího jazyka J automaticky zarovnal všechny výsledky tak, aby vytvořily pravidelnou matici. V tomto příkladu je funkce + použita jako identita, která vrací přímo svůj (jediný) argument – jedná se tedy o monadickou podobu této funkce, nikoli o (už ze své podstaty dyadický) součet:

   NB. Základní použití operátoru \.
   +\ 1 2 3 4
1 0 0 0
1 2 0 0
1 2 3 0
1 2 3 4

V předchozí kapitole jsme si ukázali, jakým způsobem lze vytvořit trojúhelníkové matice. Ty je však možné zkonstruovat i alternativním postupem demonstrovaným na následující dvojici příkladů:

   NB. Jeden ze způsobů konstrukce trojúhelníkové matice.
   *\ 1 2 3 4
1 0 0 0
1 1 0 0
1 1 1 0
1 1 1 1

   NB. Využití funkce |: provádějící transpozici matice.
   NB. (pozor - funkce |: je odlišná od funkce |.)
   |: *\ 1 2 3 4
1 1 1 1
0 1 1 1
0 0 1 1
0 0 0 1

Předchozí příklady využívající operátor \ byly poněkud netypické. Mnohem častěji se tento operátor využívá spolu s výše popsaným operátorem / pro vytvoření vektoru obsahujícího postupnou aplikaci nějaké dyadické funkce na předaný parametr, kterým je většinou vektor nebo matice (zde se již přibližujeme původnímu operátoru \ z jazyka APL, v jazyku J je zvoleno obecnější a tím pádem i universálnější řešení). Pokud je například zavolán příkaz:

   +/\ 1 2 3 4

Vygeneruje se vektor obsahující tyto hodnoty:

1 3 6 10

které vznikly následující sekvencí výpočtů:

1
1+2
1+2+3
1+2+3+4

Tento způsob použití operátoru \ je v aplikacích psaných v programovacím jazyku J poměrně často použitý, protože se s ním dají i bez použití programových smyček generovat například některé důležité číselné řady:

   NB. Prvních deset prvků posloupnosti řady faktoriálů.
   */\ 1 2 3 4 5 6 7 8 9 10
1 2 6 24 120 720 5040 40320 362880 3628800

   NB. Při náhradě vektoru (1 2 3 4 5 6 7 8 9 10) sekvencí
   NB. indexů musíme dát pozor na to, že se indexuje od 0,
   NB. tj. všechny součiny i jejich postupné součty budou
   NB. nulové.
   */\ i. 10
0 0 0 0 0 0 0 0 0 0

   NB. Korektní zápis výpočtu prvních deseti prvků
   NB. posloupnosti řady faktoriálů.
   */\ 1 + i. 10
1 2 6 24 120 720 5040 40320 362880 3628800

5. Tvorba uživatelských funkcí

V předchozích kapitolách jsme si ukázali, jakým způsobem je možné v interaktivním režimu interpretru programovacího jazyka J volat jednotlivé základní (primitivní) funkce, popř. funkce zkombinované s některým operátorem. Ovšem při tvorbě větších aplikací se nevyhneme nutnosti vytváření uživatelských funkcí, v nichž je možné definovat lokální i globální proměnné, používat řídicí struktury (podmíněné příkazy a programové smyčky) atd. Uživatelsky definované funkce mohou být monadické (s jedním parametrem), dyadické (s dvojicí parametrů) nebo lze jednomu identifikátoru (jménu) přiřadit jak monadickou, tak i dyadickou funkci. Speciálním případem funkcí jsou funkce, v nichž se na předané parametry pouze volají další uživatelské i primitivní funkce, popř. operátory, bez vytváření pomocných proměnných. Tyto speciální funkce, které jsou v mnoha ohledech velmi užitečné, si popíšeme v osmé kapitole. Nyní se ovšem budeme zabývat běžnými uživatelskými funkcemi s parametry (jedním či dvěma) a návratovou hodnotou. Obecný formát zápisu nové funkce jak v monadické, tak i dyadické formě, má tvar:

jméno_funkce =: verb define
tělo_monadické_funkce
:
tělo_dyadické_funkce
)

V tuto chvíli můžeme pro jednoduchost považovat identifikátory verb a define za klíčová slova, i když se ve skutečnosti jedná o náhradu numerických konstant s pevným významem (například konstanta 3 říká interpretru, že má vytvořit funkci, konstanta 0, že se jedná o funkci, jejíž tělo se nachází na dalších programových řádcích atd.). Mezi tělem monadické a dyadické funkce se nachází znak dvojtečky, celá funkce (resp. definice těl obou funkcí) je ukončena znakem pravé kulaté závorky (závorky tedy nejsou vyvážené, na rozdíl od použití závorek v aritmetických a logických výrazech). V případě, že uživatel potřebuje vytvořit pouze monadickou nebo jen dyadickou funkci, jejíž tělo je možné zapsat na jeden řádek, může použít zkrácenou formu zápisu funkce ukázanou pod tímto odstavcem. Povšimněte si, že tělo funkce (seznam příkazů) je při použití tohoto způsobu zápisu umístěno v apostrofech:

name =: monad : 'text of verb'
name =: dyad : 'text of verb'

6. Monadické uživatelské funkce

Monadické (jednoparametrické) funkce mohou ve svém těle přistupovat ke svému jedinému parametru, který má v tomto případě jméno y. Dyadické (dvouparametrické) funkce mají dvojici parametrů: levý je pojmenovaný x, pravý y (jedná se o stejné pojmenování, jako u monadických funkcí, což dává smysl, protože i u těchto funkcí jde o parametr, který se nachází napravo od jména funkce). Nyní si ukažme, jakým způsobem je možné vytvořit jednoduchou monadickou funkci nazvanou minus, která vrátí hodnotu svého jediného parametru, ale s opačným znaménkem (návratovou hodnotou funkce je výsledek posledního výrazu ve funkci, podobně jako například v LISPu). Jako parametr je možné předat skalární hodnotu, vektor, matici či pole o libovolné dimenzi. Tuto funkci lze vytvořit jedním ze tří způsobů:

   NB. První ze způsobů definice funkce
   NB. "minus". V tomto případě se jakoby
   NB. současně vytváří monadická i dyadická
   NB. funkce, ovšem uvede se pouze tělo
   NB. monadické funkce.
   minus =: verb define
-y
)

   NB. Druhý ze způsobů definice funkce
   NB. "minus". Zde se již explicitně uvádí,
   NB. že se jedná o funkci monadickou.
   minus =: monad define
-y
)

   NB. Třetí způsob definice funkce "minus",
   NB. při němž je tělo funkce napsáno na
   NB. jednom řádku (v apostrofech).
   minus =: monad : '-y'

Vytvořenou funkci minus si můžeme ihned otestovat, a to jak na parametrech typu skalár, tak i na vektorech a maticích:

   NB. Použití skalární hodnoty
   NB. jako parametru monadické
   NB. funkce "minus".
   minus 10
_10
   minus 42
_42
   minus _42
42
   NB. Funkce se v programovacím jazyku
   NB. "J" vyhodnocují vždy zprava doleva.
   minus 1 + 2 + 3
_6
   1 + minus 2
_1

   NB. Použití vektoru
   NB. jako parametru monadické
   NB. funkce "minus".
   minus 1 2 3 4 5
_1 _2 _3 _4 _5

   minus 1+i.5
_1 _2 _3 _4 _5

   NB. Použití matice
   NB. jako parametru monadické
   NB. funkce "minus".
   matice =: 3 3 $ i.9
   matice
0 1 2
3 4 5
6 7 8
   minus matice
 0 _1 _2
_3 _4 _5
_6 _7 _8

Snadno se taktéž můžeme přesvědčit, že interpret programovacího jazyka J hlídá, zda je uživatelská funkce minus zavolána s korektním počtem parametrů:

   NB. Pokus o zavolání dyadické funkce "minus"
   1 minus 2
|domain error: minus
|   1     minus 2

7. Dyadické uživatelské funkce

Dyadické funkce se vytváří prakticky stejným způsobem jako funkce monadické, ovšem s použitím slova dyad namísto monad. Jak již víme z předchozího textu, jsou parametry uživatelských dyadických funkcí pojmenovány x (levý) a y (pravý). Uživatelskou funkci součtu dvou hodnot (skalárů, vektorů či matic) lze tedy zapsat velmi snadno, například s použitím „jednořádkové“ for­my:

   NB. Jednořádková uživatelská funkce
   NB. "soucet" zapsaná na jednom radku
   soucet =: dyad : 'x + y'

   NB. Test, zda funkce pracuje korektne
   10 soucet 20
30

   1 2 3 soucet 4 5 6
5 7 9

Při definici monadické i dyadické funkce se stejným jménem je zapotřebí použít formu definice začínající slovy verb define. Důvod je prostý – pokud by se nejdříve definovala například monadická funkce a poté (samostatným příkazem) funkce dyadická, došlo by k přepisu definice funkce přiřazené ke zvolenému identifikátoru, stejně jako dojde při přiřazení hodnoty do proměnné k přepisu hodnoty předchozí (i =: 1, i =: 2). Monadickou i dyadickou funkci minus je tedy možné vytvořit následovně:

   NB. Definice monadické i dyadické
   NB. funkce "minus".
   minus =: verb define
- y
:
x - y
)

   NB. Test funkčnosti obou variant
   NB. funkce "minus".
   minus 10
_10

   10 minus 20
_10

   100 minus 10
90

   minus 1 2 3 4 5
_1 _2 _3 _4 _5

   minus 1+i.5
_1 _2 _3 _4 _5

   1 2 3 minus 4 5 6
_3 _3 _3

8. Tacit programming

Poslední zajímavou vlastností programovacího jazyka J, se kterou se v tomto seriálu seznámíme, je takzvaný tacit programming (přesný český ekvivalent tohoto označení mě nenapadá, proto raději zůstanu u termínu anglického, který se ostatně snadněji vyhledává). Jedná se o styl zápisu bloků programů (typicky uživatelských funkcí nebo výrazů), ve kterých se nachází volání jiných funkcí, ovšem bez explicitního udání jmen jejich argumentů (parametrů). S tímto stylem programování jsme se již mohli seznámit v seriálech o programovacím jazyku Forth a Joy, v nichž se využívalo toho, že všechny argumenty funkcí (operátorů) se nacházely na nejvyšších místech zásobníku operandů. Ve Forthu tedy bylo možné napsat například následující funkci:

:foo + * ;

která na zásobníku očekávala alespoň tři číselné hodnoty, které ovšem uvnitř funkce nebyly nikde explicitně pojmenovány ani použity. Použití této funkce bylo stejně snadné jako její zápis:

3 2 1 foo .
9

Podobným způsobem je možné vytvářet funkce i v programovacím jazyku J. Typickým příkladem je funkce pro výpočet průměru číselných hodnot uložených v nějakém vektoru. Průměr se vypočítá snadno: nejprve zjistíme součet (sumu) všech prvků (funkce + zkombinovaná s operátorem /) a následně tento součet vydělíme jejich počtem (funkce # zjistí délku vektoru). Při těchto výpočtech není nutné nikde explicitně pojmenovávat parametry – ty se použijí až při aplikaci (použití) vytvořené kombinace funkcí v další části programu:

CS24_early

   NB. mean=suma(a1..an)/n
   mean =: +/ % #

9. Literatura

  1. Linda Alvord and Norman Thomson, „Easy-J: An Introduction to the World's most Remarkable Programming Language
    October 2002
  2. Ulf Grenander, „Mathematical Experiments on the Computer,
    Academic Press, 1982, ISBN 0–12–301750–5.
  3. K. E. Iverson, „A Programming Language“,
    Wiley, 1962.
  4. K. E. Iverson, „Algebra : an algorithmic treatment“,

    APL Press 1977, Copyright 1972 by Addison Wesley,

    Preliminary Edition entitled „Elementary Algebra

    Copyright 1971 by IBM Corporation.
  5. K. E. Iverson, „Elementary analysis“,

    APL press 1976, Preliminary Edition „Elementary Functions

    Copyright 1974 by IBM Corporation ISBN 0–917326–01–6
  6. K. E. Iverson, „A personal view of APL,
    IBM Systems Journal,
  7. C. Reiter, „Fractuals Visualization and J“,
    Iverson Software, Inc, 1995 ISBN 1–895721–11–3.
  8. J Phrases,
    Iverson Software, 1996, ISBN 1–895721–12–1
  9. Exploring Math“, Iverson Software, 1996, ISBN 1–895721–13-X
  10. J Primer,
    Iverson Software, 1996, ISBN 1–895721–14–8

10. Odkazy na Internetu

  1. Tacit programming
    http://en.wikipedia.org/wiki/Tacit_programming
  2. Pure functions in APL and J
    http://portal.acm.org/citation.cfm?id=114065&dl=GUIDE&coll=GUIDE
  3. Learning J (Roger Stokes)
    http://www.jsoftware.com/help/learning/contents.htm
  4. J: a modern, high-level, general-purpose, high-performance programming language
     http://www.jsoftware.com/
  5. K, Kdb: an APL derivative for Solaris, Linux, Windows
     http://www.kx.com
  6. Vector (obsahuje odkazy na články, knihy a blogy o programovacích jazycích APL, J a K)
     http://www.vector.org.uk/
  7. APL – A Glimpse of Heaven
    http://www.vector.org.uk/archive/v231/legrand.htm
  8. APL Interpreters
    http://www.vector.org.uk/?area=interpreters
  9. APL_(programmin­g_language
    http://en.wikipedia.org/wiki/APL_(programming_lan­guage
  10. APL FAQ
    http://www.faqs.org/faqs/apl-faq/
  11. APL FAQ (nejnovější verze)
    http://home.earthlink.net/~swsirlin/apl.faq.html
  12. A+
    http://www.aplusdev.org/
  13. Rosetta Code
    http://rosettacode.org/wiki/Main_Page

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

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.