| Paradigma | multiparadigmatický |
|---|---|
| Vznik | 1988 |
| Autor | Stephen Wolfram |
| Vývojář | Wolfram Research |
| První vydání | 1988 |
| Poslední verze | 13.1.0 (2022) |
| Typová kontrola | dynamická |
| Hlavní implementace | Mathematica,Mathics,Expreduce |
| Ovlivněn jazyky | Lisp[1],APL[1],SMP[1],C |
| Ovlivnil jazyky | Jupyter[2][3] |
| OS | multiplatformní |
| Licence | proprietární licence |
| Web | wolfram.com/language,wolframlanguage.org |
| Přípona souboru | .nb, .wl, .wls; dříve též .cdf, .m |
Wolfram Language či jenWolfram (dále jen WL; dříve téžMathematica, pro podrobnosti viz oddíl"Pojmenování") jeuniverzálnívyšší[4]programovací jazyk vyvíjený společnostíWolfram Research. Ústředním konceptem jazyka jsouvýrazy — výrazem jsou reprezentovány i takové části jazyka jakopodmíněný příkaz čicykly, jež jsou obvykle v jiných jazycích jakoC čiPython vyjadřovány pomocípříkazů. Kód tak má přirozenoustromovou strukturu složenou z vnořených výrazů, jež lze přitom upravovat podobně jako data. Dalším ústředním konceptem jazyka jsou vzory (angl.patterns), které umožňují pružné vyhledávání a nahrazování částí kódu či dat pomocí nahrazovacích pravidel. WL jeinterpretovanýdeklarativní jazyk[4], jenž umožňujesymbolické,funkcionální iprocedurální programování s velkou mírouabstrakce[4].
WL obsahuje množství funkcí z různých oblastímatematiky,statistiky,zpracování dat čistrojového učení. Jazyk umožňuje tvorbu2D i3D grafiky, manipulaci se zvukem či videem, tvorbu interaktivních uživatelských rozhraní, tvorbuwebových rozhraní apod. Integrální součástí jazyka jsou funkce pro přímý přístup k datům různého druhu uloženým na vzdálených serverech[pozn. 1]. Podporovány jsousymbolické inumerické výpočty,paralelní výpočty i napojení na jiné jazyky jakoJava,Python čiJulia[5]. Kód ve WL lze pro zvýšení efektivityzkompilovat do jazykaC či do nízkoúrovňové reprezentaceLLVM.
V současnosti jedinou plnohodnotnou implementací jazyka WL je systémMathematica[pozn. 2]. WL samotný je vyvíjený v jazycíchC aJava jakomultiplatformní jazyk[4] běžící na systémechWindows,macOS aLinux. Rozšíření jazyka WL mezi uživateli je spíše omezené. Podle žebříčkuTIOBE[7] se jazyk WL nedostává do první stovky nejpoužívanějších jazyků. ŽebříčekIEEE Spectrum k roku 2022[8] vypisuje 57 nejoblíbenějších jazyků, přičemž WL mezi nimi nefiguruje. Podobně není WL v seznamu nejoblíbenějších jazyků na projektu RedMonk[9] a v žebříčkuPYPL index[10] není WL ani zahrnut do seznamu sledovaných jazyků.
FirmaWolfram Research od roku 1988 vyvíjí programMathematica, který zpočátku uživateli umožňoval provádět různématematické operace v závislosti na zadaných příkazech. Samotné jméno "Mathematica" bylo navrženoStevem Jobsem[11] a tento produkt byl inzerován sloganem"A System for Doing Mathematics by Computer"[12], to jest"systém pro dělání matematiky počítačem". S postupem času se sada příkazů rozšiřovala, čímž vzniknulprogramovací jazyk s funkčností přesahující rámecmatematiky, přičemž se pro tento jazyk též ustálilo pojmenování "Mathematica". Tento název tak označoval jak konkrétní softwarový produkt, tak programovací jazyk, který tento produkt implementuje.
S verzí 10.0.0 došlo k oddělení těchto dvou konceptů[13] spolu s přejmenováním některých produktů společnosti a změnou jejich inzerování. Jméno "Mathematica" tak označujevývojové prostředí určené pro tvorbu kódu v jazyce, jež nese jméno "Wolfram language", to jest "jazyk Wolfram". Zavedené změny nicméně nejsou zcela dobře vymezeny, což vedlo k rozporuplnému přijetí mezi stávajícími uživateli a zmatení v užívaném názvosloví[14][15][16][17]. Na oficiálních stránkách[1] je rozdíl mezi Wolfram language a Mathematicou popsán slovy:"V prvním přiblížení, Wolfram Language = Mathematica + Wolfram|Alpha + Cloud + víc. Je kompatibilní s Mathematicou, ale je jejím podstatným rozvinutím, včetně znalostí, použití a mnoha nových myšlenek,"[pozn. 3] kdeWolfram|Alpha je služba poskytovaná firmou Wolfram Research založená zčásti nazpracování přirozeného jazyka a slovemCloud jsou myšlenycloudové služby a s tím související funkce nabízené téže firmou.
| 1988 | 1.0 (červen) |
|---|---|
| 1989 | 1.2 (srpen) |
| 1990 | |
| 1991 | 2.0 (leden) |
| 1992 | 2.1 (červen) |
| 1993 | 2.2 (červen) |
| 1994–1995 | |
| 1996 | 3.0 (září) |
| 1997–1998 | |
| 1999 | 4.0 (květen) |
| 2000 | 4.1 (listopad) |
| 2001 | |
| 2002 | 4.2 (červen) |
| 2003 | 5.0 (červen) |
| 2004 | 5.1 (listopad) |
| 2005 | 5.2 (červenec) |
| 2006 | |
| 2007 | 6.0 (květen) |
| 6.0.1 (červenec) | |
| 2008 | 6.0.2 (únor) |
| 6.0.3 (červen) | |
| 7.0 (listopad) | |
| 2009 | 7.0.1 (březen) |
| 2010 | 8.0 (listopad) |
| 2011 | 8.0.1 (březen) |
| 8.0.4 (říjen) | |
| 2012 | 9.0.0 (listopad) |
| 2013 | 9.0.1 (leden) |
| 2014 | 10.0.0 (červenec) |
| 10.0.1 (září) | |
| 10.0.2 (prosinec) | |
| 2015 | 10.1 (březen) |
| 10.2 (červenec) | |
| 10.3 (říjen) | |
| 10.3.1 (prosinec) | |
| 2016 | 10.4 (březen) |
| 10.4.1 (duben) | |
| 11 (srpen) | |
| 11.0.1 (září) | |
| 2017 | 11.1 (březen) |
| 11.1.1 (duben) | |
| 11.2 (září) | |
| 2018 | 11.3 (březen) |
| 2019 | 12 (duben) |
| 2020 | 12.1 (březen) |
| 12.1.1 (červen) | |
| 12.2 (prosinec) | |
| 2021 | 12.3 (květen) |
| 12.3.1 (červenec) | |
| 13 (prosinec) | |
| 2022 | 13.0.1 (únor) |
| 13.1 (červen) |
WL jesymbolický jazyk, kde je s kódem nakládáno stejným způsobem jako s daty — přístup známý jakohomoikonicita[4], který se uplatňuje i v jiných jazycích jako třebaLisp. Kniha"Mathematica programming — an advanced introduction"[19] uvádí tři základní principy, na nichž je WL vybudován. Prvním z nich jsou symbolické výrazy jako stavební blok jazyka. Druhým jsou vzory[4] a jejich použití pro úpravu výrazů s pomocí nahrazovacích pravidel. Třetím principem je pak způsob, jakým jsou výrazy a jejich úpravy vyhodnocovány. Každý princip je podrobněji představen v samostatné podsekci níže. WL jeinterpretovaný jazyk využívajícíJIT kompilace[4]. Ze symbolického charakteru jazyka plyne jehodynamické typování[1] afunkcionální přístup k úpravě kódu[4]. Ačkoliobjektově orientované programování není ve WL přímo podporováno, existují různé způsoby jak ho emulovat[pozn. 4].
Výpočetní systém, na kterém běží WL, se skládá ze dvou hlavních částí — výpočetního jádra (angl.kernel) a front endu (angl.front end). Výpočetní jádro se stará o samotné výpočty, zatímco front end slouží k interakci s uživatelem. Vkládání vstupů uživatelem a jejich formátování stejně jako pokročilé funkce vykreslování výstupů včetněmatematické sazby,grafiky či přehrávání zvuku má na starosti front end. S tím je svázán i fakt, že mnoho funkcí WL bez front endu nefunguje. Jádro komunikuje s front endem pomocí protokolu WSTP (Wolfram Symbolic Transfer Protocol[25], dříve známý pod jménem MathLink). Tento protokol lze použít i pro komunikaci mezi jádrem a externí aplikací vyvinutou v jiném jazyce, přičemž oficiálně jsou takto podporována mimo jiné propojení s jazykyJava (knihovna J/Link[26]),R (knihovna RLink[27]) či s.NETframeworkem (knihovna .NET/Link[28]).
Při vývoji WL se klade důraz na jehozpětnou kompatibilitu[4]. V minulosti byly hlavní verze WL vydávány zhruba jednou za tři roky, viz přehled vpravo.

a + Sin[b*c] ve forměsyntaktického stromu. Tuto reprezentaci výrazu lze získat funkcíTreeForm.Každý objekt ve WL, to jest kód, data, obrázky, dokumenty, rozhraní, programy atd., je představován symbolickým výrazem (angl.expression)[4][29]. Výrazy mohou být dvojího druhu, a to buď atomární anebo normální. Atomárních výrazů je omezené množství, jedná se (především) očísla,řetězce a symboly[pozn. 5]. Všechno ostatní jsou normální výrazy, které mají obecnou strukturu následujícího tvaru:
hlava[arg1,arg2,...]
kdehlava je hlavička výrazu, jež samotná je buď symbol anebo normální výraz, a kde dále objektyarg1,arg2, atd. tvoří tělo výrazu a samy mohou být buď atomárními či normálními výrazy. Tímto přirozeně vzniká stromová struktura výrazů[4][30] a následně i celého kódu, viz obrázek vlevo. S touto strukturou lze nakládat jako s daty — lze například přistupovat k jejím částem pomocí indexů[pozn. 6], podobně jako lze přistupovat k prvkům vícerozměrného pole. Příkladem normálního výrazu je i samotné volání funkce. NapříkladSin[x] je nejen volání funkcesinus naproměnnoux, ale současně i výraz s hlavičkouSin a tělem obsahujícím argumentx. Každý konstrukt má ve WL reprezentaci výše uvedeného tvaru, která se nazýváFullForm, takže například součet dvou čísel1 + 2 je interně reprezentován jakoPlus[1,2], to jest výraz s hlavičkouPlus. Výrazy jsou ve WLimutabilní struktury, kde jen vyhrazené funkce mohou výraz měnit "in place"[4].
Vzory (angl.patterns)[31] jsou svým způsobem šablony, kterým může vyhovovat současně vícero různých výrazů. Tyto šablony lze použít pro vyhledání nějaké části výrazu, či pro zkontrolování, zda je daný výraz správného tvaru. Tak například výrazSin[x] je sice odlišný od výrazuSin[y], oba bychom ale mohli popsat slovy "funkcesinus volaná na nějakou proměnnou". Takovýto krátký popis lze formalizovat pomocí vzoru ve tvaruSin[_], kdepodtržítko_ je znak představující "cokoliv". Tyto a podobné vzory lze uplatnit při definicích funkcí.Konstantní funkcikonst, která na jakýkoliv vstup vrátí číslo 42, lze definovat způsobem:konst[_] = 42. Pokud je nutno se na vstup odkazovat jako naproměnnou, lze mu dát jméno. Napříkladx_ označuje "cokoliv, čemuž jsme dali jméno x". Funkci, jež má pro jakoukoliv vstupní hodnotu vrátit jejídruhou mocninu, tak lze definovat následovně:
f[x_]:=x^2
Ve výše uvedeném vzoru přitom není vůbec řečeno, že vstupní hodnotou musí býtčíslo — lze použít skutečně cokoliv:
{f[2],f["retez"],f[Sin]}(* vrátí: {4, "retez"^2, Sin^2} *)
Ačkoliv to třeba nemusí dávat smysl, funkcef aplikovala druhou mocninu i nařetězec "retez" aidentifikátor funkceSin. Tímto způsobem WL implementujepolymorfizmus[4].
Vzory mohou mít velmi složitou strukturu. Způsob, jakým WL určí, zda daný výraz vyhovuje zadanému vzoru, se v angličtině nazývápattern matching. Úpravy výrazů pak probíhají pomocí nahrazovacích pravidel (angl.(transformation) rules)[32] tvaruvzor->vyraz, které danou část výrazu vyhovující vzoruvzor nahradí novým (pod)výrazem tvaruvyraz. Výše uvedenou funkcif lze vyjádřit jako nahrazovací pravidlox_ -> x^2[pozn. 7]. Aplikace pravidla se zapisuje jako/. a tak výše uvedený kód lze přepsat do tvaru:
{2/.x_->x^2,"retez"/.x_->x^2,Sin/.x_->x^2}(* vrátí: {4, "retez"^2, Sin^2} *)
Ve skutečnosti je jakákoliv funkce vyjádřena interně jako sada odpovídajících nahrazovacích pravidel.[33][pozn. 8]
Výpočetní jádro WL si udržuje interní databáziglobálních nahrazovacích pravidel, v nichž jsou obsaženy jakdefinice vestavěných i uživatelem definovanýchfunkcí, tak přiřazení doproměnných. Jakmile je výraz ve WL odeslán do výpočetního jádra, prochází jádro tuto databázi a zjišťuje, zda levé strany některých pravidel vyhovují zadanému výrazu či některé jeho části. Je-li takové pravidlo nalezeno, je na výraz aplikováno, čímž dojde k jeho změně. Tato změna odstartuje další prohledávání téže databáze, kde jsou nyní hledána pravidla vyhovující novému tvaru výrazu. Tento proces probíhá tak dlouho, dokud už nelze výraz žádným z existujících pravidel upravit. Tento výsledný výraz je následně vrácen uživateli[34][35].
Pořadí, ve kterém jsou výrazy takto vyhodnocovány, lze nicméně upravovat, a to buď pomocí funkcíEvaluate,Unevaluated,Hold apod., anebo pomocí atributů funkcíHoldAll,HoldFirst, atd.[36] Máme-li například funkci, jež má vrátit hlavičku výrazu, na který je volána, můžeme obdržet neočekávané výsledky:
f[h_[x_]]:=h;(* definice *)f[hlava[telo]](* vrátí: hlava *)f[Sin[x]](* vrátí: Sin *)f[Sin[Pi/2]](* vrátí: f[1] *)
Ačkoli bychom chtěli, aby i v posledním řádku vrátila funkce symbolSin, obdržíme výsledekf[1]. Důvod je ten, že se nejprve vyhodnotil výrazSin[Pi/2] na hodnotu 1 a teprve tato hodnota byla vložena do funkcef. Protože funkcef ale nemá přiřazenu definici pro případ argumentů, které nemají tvar normálního výrazu, zůstává funkce nevyhodnocena, čímž obdržímef[1]. Toto chování lze napravit tak, že argument zabalíme do výrazuUnevaluated, který zabrání tomu, aby se daný výraz vyhodnotil:
f[Unevaluated[Sin[Pi/2]]](* vrátí: Sin *)
Téhož chování lze dosáhnout i tak, že funkcif nastavíme atributHoldAll, který zamezí tomu, aby k vyhodnocování argumentů docházelo obecně aUnevaluated tak není potřeba:
SetAttributes[f,HoldAll]f[Sin[Pi/2]](* vrátí: Sin *)
Níže je podán krátký výběr nejzákladnějších prvků jazyka WL. Důraz je ve WL obecně kladen nafunkcionální přístup, kdy například místofor cyklů pro úpravupolí prvek po prvku lze použít funkciMap, která má jako první parametr funkci, jež se má na prvky uplatnit, a jejímž druhým parametrem je upravované pole. Dalším specifikem je používání vzorů, což jsou obdobyregulárních výrazů, které lze použít například pro vyhledávání prvků v poli se zadanými vlastnostmi či v definicíchfunkcí.
Syntaxe se v mnohém podobá známým jazykům jako je jazykC. Až na speciální znaky a znaky, jež mají ve WL předdefinovanou funkci, lze proidentifikátory použít ve WL celou saduUnicode[37] včetně písmen české abecedy, přičemž identifikátory nemohou začínat číslicí. V praxi se přesto většinou používají jen písmena anglické abecedy. Některé předdefinované interní konstanty a proměnné navíc začínají znakem dolaru$. Na rozdíl od mnoha jiných jazyků nelze však v identifikátoru použítpodtržítko, které v WL hraje funkci zástupného symbolu ve vzorech. WL jecase sensitive.
V sekci"Ukázky" níže je vypsána řada příkladů ilustrující různou funkcionalitu jazyka WL. V článku "Syntaxe a sémantika programovacího jazyka Wolfram Language" lze pak nalézt další podrobnosti.
Nápověda se programově vyvolá zapsánímotazníku na začátek řádky, po němž následuje dotazovaný symbol, např.?Sin. Komentáře jsou vloženy mezi závorky s hvězdičkami způsobem(* toto je komentář *). Znak procenta% je používán pro vyvolání posledního výsledku:
a=1;(* do proměnné a ulož hodnotu 1 *)b=a+2;(* proměnná b obsahuje hodnotu 3 *)%(* vrátí: 3 *)
Čísla mohou být jednoho z následujících typů:Integer (celá čísla, nekonečná přesnost),Rational (racionální čísla, nekonečná přesnost),Real (reálná čísla splovoucí řádovou čárkou, libovolně zvolitelná přesnost[4]),Complex (komplexní čísla, jejichž reálná a imaginární část může být celá, racionální či reálná). Navíc je podporována řada konstant jakočíslo píPi čiEulerovo čísloE. S čísly lze provádět obvykléaritmetické operace:
3+4(* sčítání; vrátí: 7 *)3-4(* odčítání; vrátí: -1 *)3*4(* násobení; vrátí: 12 *)3/4(* podíl dvou celých čísel; vrátí: 3/4 *)3.0/4.0(* podíl dvou reálných čísel; vrátí: 0.75 *)Quotient[3,4](* celočíselné dělení; vrátí: 0 *)Mod[3,4](* modulo operace; vrátí: 3 *)3^4(* mocnina; vrátí: 81 *)2.3+4I(* komplexní číslo; I označuje imaginární jednotku *)
Řetězce se zapisují pomocí dvojitých uvozovek a speciální znaky lzeescapovat lomítkem. Dva a více řetězců lze spojit operátorem<>:
"toto je řetězec""řekla: \"takčionak\" \\ následuje\nnový řádek a\ttabulátor"(* vypíše:řekla: "tak či onak" \ následujenový řádek a tabulátor*)"první"<>" a "<>"druhý"(* vrátí: "první a druhý" *)
Proměnné, konstanty či pojmenované funkce jsou reprezentovány symboly. Obecně jsou konstrukty ve WL reprezentovány jakovýrazy (angl.expressions), které mají hlavičku, za níž v hranatých závorkách následuje tělo výrazu. Například volání funkcesinusSin[0.2] lze chápat jako výraz s hlavičkouSin, v jehož těle je reálné číslo. Podobně například komplexní číslo lze reprezentovat jako výrazComplex[1,2], jehož hlavičkou jeComplex a tělo tvoří dvě čísla 1 a 2.
Ve WL existují dva základní druhypřiřazení: přímé= a odložené:=[38].Odložené přiřazení vyhodnocuje pravou stranu až ve chvíli, kdy je symbol na levé straně volán. Rozdíl mezi oběma přiřazeními lze nejsnáze nahlédnout, je-li na pravé straně generováno náhodné číslo. Zatímco do proměnnéa níže je uloženo jedno dané číslo, které je při volání této proměnné vráceno, v případě proměnnéb je funkceRandomReal vždy znova zavolána při každém volání této proměnné:
a=RandomReal[];(* přímé přiřazení *)b:=RandomReal[];(* odložené přiřazení *){a,b}(* vrátí: {0.86258,0.480284} *){a,b}(* vrátí: {0.86258,0.705826} *)
Podporovány jsou standardní porovnávací operátory, přičemž nerovnost se zapisuje jako vykřičník následovaný rovnítkem!=:
1<2(* ostrá nerovnost; vrátí: True *)1>=2(* neostrá nerovnost; vrátí: False *)1==1.(* rovnost; vrátí: True *)1!=2(* nerovnost; vrátí: True *)
Logické operátory implementujízkrácené vyhodnocení, a tak je-li např. v operátoruAND z prvního argumentu zřejmé, že je výsledekFalse, další argumenty se již nevyhodnocují. Negace se zapisujevykřičníkem:
10<12&&"ret"!="aha"(* AND; vrátí: True *)10<12||(Print["druhý argument"];False)(* OR; vrátí: True; nic nevypíše, protože již první argument je True a celý výraz tak musí být True *)!True(* negace; vrátí: False *)
Podmíněný příkaz je představován funkcíIf, jejímž prvním parametrem je podmínka, druhým parametrem je výraz, který se vyhodnotí, je-li podmínka pravdivá, a třetím parametrem je výraz vyhodnocený, je-li podmínka nepravdivá. FunkceIf má ještě nepovinný čtvrtý parametr, který je vyhodnocen, nelze-li určitpravdivostní hodnotu podmínky:
If[1<2,"mensi","vetsi"](* vrátí: "mensi" *)If[x<y,"mensi","vetsi","nevim"](* vrátí: "nevim" *)
Protože proměnnéx ay nemají v kódu výše přiřazenu žádnou hodnotu, nelze vyhodnotit nerovnost a funkceIf tak vrátí čtvrtý argument.
Ačkoli WL podporuje tradiční cykly jakofor cyklusFor,while cyklusWhile arepeat-until cyklusUntil, není používání for cyklu kvůli jeho pomalé implementaci doporučeno[1]. Místo toho se doporučuje používání funkcí jakoDo pro opakované provádění kódu,Table pro tvorbu polí čiNest pro tvorbu vnořených struktur. Další alternativou je používání funkceMap, jež aplikuje danou funkci na každý prvek pole:
pole={0,0,0,0,0};For[i=1,i<=5,i++,pole[[i]]=i^2];pole(* vrátí: {1, 4, 9, 16, 25} *)Table[i^2,{i,5}](* vrátí: {1, 4, 9, 16, 25} *)Map[#^2&,{1,2,3,4,5}](* vrátí: {1, 4, 9, 16, 25} *)
Standardní vyhodnocování kódu lze programově přerušit funkcemiThrow čiConfirm, jejichž volání musí být po řadě zachyceno funkcemiCatch čiEnclose. Chybové hlášky a varování lze vypsat voláním funkceMessage. Například:
Catch[a=1;Throw[chyba];a=3;](* vrátí: chyba; proměnná a má hodnotu 1 *)
Základními dvěmadatovými strukturami ve WL jsoupole neboliseznamy (List)[39] aasociativní pole (Association)[40]. Pole jsouimutabilní datové struktury, které lze indexovat a lze do nich ukládat jako prvky libovolné další výrazy, které nemusejí být stejného typu. Do jednoho pole tak lze uložit čísla, řetězce, obrázky, zvukové nahrávky apod. Indexování se provádí pomocí dvojitýchhranatých závorek, přičemž počáteční index je roven jedné a pro indexování od konce lze použít záporných čísel. Pole jsou zapisována dosložených závorek:
pole={5,-14,42.,"řetězec",Sin};(* v poli lze ukládat i funkce *)pole[[2]](* vrátí: -14 *)pole[[-2]](* vrátí: "řetězec" *)pole[[3]]=1;(* do třetího prvku uloží číslo 1; výjimka z imutability *)pole(* vrátí: {5, -14, 1, "řetězec", Sin} *)
Asociativní pole se zapisují do speciálních závorek skládajících se zesvislic aúhlových závorek, kde je každý pár (klíč, hodnota) propojen pomocí šipky->. Asociativní pole podporují jednak vyhledání hodnoty pomocí klíče, který se vkládá do jednoduchých hranatých závorek, jednak i indexování známé z normálních polí, a to pomocí dvojitých hranatých závorek. Klíčem může být libovolný výraz:
asoc=<|"a"->5,var->-14,345->42.,"klic"->Sin|>;asoc["a"](* vrátí: 5 *)asoc[[2]](* vrátí: -14 *)asoc[[3]]=1;(* do třetí hodnoty uloží číslo 1 *)asoc(* vrátí: <|"a" -> 5, var -> -14, 345 -> 1, "klic" -> Sin|> *)
Funkce lze definovat dvěma způsoby a to buď jako symboly, anebo jakoanonymní funkce, které se ve WL označují jakoryzí funkce (angl.pure functions)[41]. První způsob přiřazuje k danému symbolu definici, jejíž standardní syntaxe zní následovně:
umocni[x_]:=x^2
kdeumocni jeidentifikátor funkce,x_ je vzor odpovídající vstupnímu parametru a znak:= vyjadřuje odložené vyhodnocení, na jehož pravé straně je tělo funkce. Volání takové funkce probíhá pomocí hranatých závorek:
umocni[3](* vrátí: 9 *)umocni[y](* vrátí: y^2 *)
Jak vidno, pracovat lze i se symboly, které nemají přiřazenu hodnotu, jako v případě symboluy výše.
Tělo funkce může být značně složitější a vynucovat si taklokální proměnné. V takovém případě lze použít například blokové strukturyBlock čiModule:
složitějšíFunkce[x_,y_]:=Module[{z=0},(* z je lokální proměnná *)If[x<0,z=1];Return[y^z];(* příkaz Return lze vynechat a psát jen y^z bez koncového středníku *)];složitějšíFunkce[1,2](* vrátí: 1 *)složitějšíFunkce[-1,2](* vrátí: 2 *)z(* vrátí: z; mimo tělo funkce totiž z nemá přiřazenu žádnou hodnotu *)
Funkce jsou ve WLfirst-class objekty a tak lze s nimi manipulovat jako s běžnými proměnnými:
mojeFunkce=umocni;mojeFunkce[3](* vrátí: 9 *)
Ryzí funkce lze zapisovat speciální syntaxí používajícíkřížek# k označení nepojmenovaných vstupů, přičemž ke konci těla funkce se připojujeampersand&. Výše definovanou funkci umocni tak lze přepsat jako ryzí funkci do tvaru:
umocni=(#^2)&;umocni[3](* vrátí: 9 *)
Velkou kapitolu tvoří ve WLvzory (angl.patterns)[42][43] anahrazovací pravidla (angl.rules), jež umožňují flexibilní manipulaci s daty či kódem a poskytují tak jistou alternativu ke standardním funkcím. Máme-li napříkladpole čísel, kde chceme každý výskyt čísla 3 nahradit řetězcem"tři", lze toto učinit následujícím zápisem:
{1,2,3,4,3,2,1}/.3->"tři"(* vrátí: {1, 2, "tři", 4, "tři", 2, 1} *)
Tento zápis se skládá z výrazu, v němž chceme provéstsubstituci, v příkladu výše tedy číselné pole{1, 2, 3, 4, 3, 2, 1}, a zápisu/. 3->"tři"[pozn. 9], kde3->"tři" je samotné nahrazovací pravidlo, jež udává, jaká substituce se má provést. Konečně znaky/. jsousyntaktický cukr pro funkciReplaceAll, která provádí samotné nahrazení. Je-li nahrazovacích pravidel udáno více, je nutno je zabalit dosložených závorek, v případě jediného pravidla toto nutné není:
{1,2,3,4,3,2,1}/.{2->"dva",3->"tři"}(* vrátí: {1, "dva", "tři", 4, "tři", "dva", 1} *)
Stejně tak lze upravovat další výrazy, napříkladalgebraické výrazy či části kódu:
x^3+3x^2+5x+1/.x->y(* vrátí: y^3 + 3 y^2 + 5 y + 1 *)x^2/.x->2(* vrátí: 4 *)
Podobně jako u přiřazení, i u nahrazovacích pravidel existujeodložená varianta, která se zapisuje symboly:>, kde se pravá strana pravidla vyhodnotí až ve chvíli volání. Chceme-li každý výskyt celého čísla v poli nahradit jeho druhou mocninou, lze toto provést následovně[pozn. 10]:
{2,3,x,y}/.x_Integer:>x^2(* vrátí: {4, 9, x, y} *)
Způsob, jakým jsou vzory používány pro nalezení odpovídající části kódu, se anglicky nazývápattern matching[42], což lze přeložit jakoporovnávání se vzorem.
Součástí WL je kromě funkcí a interních proměnných i přístup k datům uchovávaným na serverech společnosti Wolfram Research. Tato firma označuje WL jakoknowledge based[44], to jestzaložený na znalostech. Jedná se například oastronomická,klimatická čifinanční data, jež lze získat funkcemi jakoWeatherData,FinancialData atd. Alternativním přístupem je vyjádření znalostí pomocíontologie, v níž je každý objekt představován výrazemEntity. Například počet obyvatelČeské republiky lze získat voláním
Entity["Country","CzechRepublic"]["Population"]
Obsah stránek naWikipedii lze obdržet funkcíWikipediaData, položky z projektuWikidata lze získat voláním funkceWikidataData. Podklady funkcí jakoGeoGraphics, jež slouží pro práci sgeografickými daty, jsou založeny na mapách tvořených v rámci projektuOpenStreetMap. Přímo z editoru WL lze vyvolat i funkcionalitu projektuWolfram|Alpha a to buď funkcíWolframAlpha, anebo speciální syntaxí, kdy jekurzor přesunut na začátek prázdného řádku a poté je dvakrát zmáčknuta klávesa prorovnítko. Vyvolá se tak speciální řádka, do níž lze vložit dotaz v přirozenéangličtině, pod níž se vykreslí zpracovaný výstup.
Vývojář WL udržuje kromě toho několik online repozitářů poskytujících dodatečná data a funkce:
ResourceObject, jenž obsahuje název zdroje.NetModel.ResourceFunction.PacletInstall.Databin zasílat kontinuálně naserver a pak je kdykoliv ze serveru stáhnout a zpracovat.[pozn. 11]Pro ilustraci používání výše uvedených zdrojů přímo z editoru WL uveďme použití funkcí z repozitáře Wolfram Function Repository. Řekněme například, že máme dvěkřivky a chceme spočístplochu sevřenou mezi těmito křivkami. Nevíme ale, jakou funkci k tomu použít, přičemž podobná funkce se v základní sadě funkcí WL nenachází. Můžeme proto zkusit vyhledat tuto funkci v online repozitáři na základě klíčových slov, která v aktuálním případě zvolíme jako "area" (to jest "plocha") a "curve" (to jest "křivka"). Pokud taková funkce existuje, můžeme jí poté rovnou použít:
ResourceSearch["area curve"](* vyhledej funkci v repozitáři na základě klíčových slov "area" a "curve" *)(* volání funkce ResourceSearch vrátí interaktivní databázi relevantních dostupných funkcí *)(* na základě popisků v databázi usoudíme, že námi hledaná funkce se jmenuje "AreaBetweenCurves" *)(* v databázi lze nalézt i odkaz na dokumentaci této funkce *)ResourceFunction["AreaBetweenCurves"][{x,x^2},{x,0,1}](* voláme funkci ResourceFunction["AreaBetweenCurves"] *)
Výpočetní systém automaticky stáhne definici dané funkce z online repozitáře do lokálního výpočetního jádra a tuto funkci tak lze rovnou použít.
Výchozím pracovním prostředím pro psaní kódu ve WL je tak zvanýnotebook, kde je kód strukturován do hierarchie elementárních částí zvanýchbuňky (angl.cells). Příkazy jsou psány do vstupních buněk a po vyhodnocení vstupní buňky je výsledek výpočtu vrácen do výstupní buňky, která se automaticky pod tou vstupní vytvoří. Buňky lze dále seskupovat do větších celků a utvářet tak strukturu kódu podobnou kapitolám a podkapitolám známým z psanýchknih. Buňky plní různé role, lze vkládat i čistě textové buňky či nadpisy. Tyto buňky nejsou při běhu kódu vyhodnoceny a mohou tak zastupovat funkcikomentářů.
Každá vstupní buňka je uvedena řetězcem"In[n]:=", kden je její pořadové číslo. Výstup kódu obsaženého v takové buňce je vypsán pod tuto buňku do nové výstupní buňky, jež je uvozena řetězcem"Out[n]=". Konkrétní kód v editoru, jakým je tradičněMathematica, pak může vypadat následovně:
In[1]:=1+2*3Out[1]=7
Spočtiobsahkruhu
In[2]:=polomer=0.2;obsahKruhu=Pi*polomer^2;
In[3]:=obsahKruhuOut[3]=0.125664
Druhá buňka byla nastavena jako textová buňka a tak není její obsah vyhodnocen. Ve třetí vstupní buňce je specifikováno více příkazů. Jejich výstup je středníky potlačen a výstup tak není vypsán.
Interně je každá buňka představována výrazemCell[obsah, styl, volby], kdeobsah může být buď čistý text, anebo strukturovanější data zabalená do výrazu s hlavičkouBoxData;styl označuje styl buňky, jako například vstupní ("Input"), výstupní ("Output"), textová ("Text"), titul ("Title") apod.; avolby jsou dodatečná nastavení buňky, jakým může být například barva pozadí, čas poslední změny dané buňky či identifikační číslo buňky. Buňka tedy obsahuje více informací, než které jsou uživateli v editoru přímo přístupné a z tohoto pohledu nelze kód notebooku označit jakoWYSIWYG.
Vypiš text "Ahoj světe!":
Print["Ahoj světe!"];
DefinujFibonacciho posloupnost:
f[0]=0;f[1]=1;f[n_]:=f[n-1]+f[n-2]
Tato implementace je neefektivní, protože při výpočtu daného prvkuposloupnosti jsourekurzivně počítány všechny prvky předchozí. Tomu lze předejít využitímmemoizace, kde je každý prvek spočten jen jednou a poté držen v paměti[50]:
f[0]=0;f[1]=1;f[n_]:=f[n]=f[n-1]+f[n-2]
Spočtifaktoriál:
f[0]=1;f[n_]:=nf[n-1]
Podobně jako výše u Fibonacciho posloupnosti lze i zde využít memoizace.
Provádět operace s poli lze několika způsoby, které si ilustrujeme na příkladu, kde je cílem spočístdruhou mocninu každého prvku zadaného jednorozměrného pole.
For cyklu:pole={1,2,3,4};For[i=1,i<=Length[pole],i++,pole[[i]]=pole[[i]]^2;];pole(* vrátí: {1, 4, 9, 16} *)
Map:#^2&/@{1,2,3,4}(* vrátí: {1, 4, 9, 16} *)
Zde je ryzí funkce#^2& aplikována na každý prvek pole zápisem/@, jenž odpovídá volání funkceMap.
Listable:{1,2,3,4}^2(* vrátí: {1, 4, 9, 16} *)
FunkcePower, kterou jsme vyvolalistříškou^, má atributListable. Je-li funkce s tímto atributem zavolána na seznam, to jest výraz s hlavičkouList, je tato funkce automaticky aplikována na každý prvek seznamu. Tento atribut mají například i funkceSin,Plus čiDivide.
Ve WL má mnoho funkcí ekvivalentní zkrácený zápis poskytujícísyntaktický cukr pro kompaktnější vyjádření. Pro příklad uvažme polea = {12, p, {b, c}, {}}, kde je naším cílem nahradit každý jeho prvek, jenž je sám seznamem o alespoň jednom prvku, jeho posledním prvkem. To lze provést následujícím kódem:
anovy={};For[i=1,i<=Length[a],i++,If[Head[a[[i]]]==List&&Length[a[[i]]]>=1,elem=a[[i,-1]],elem=a[[i]]];AppendTo[anovy,elem]];anovy(* vrátí: {12, p, c, {}} *)
S použitím vzorů a funkcionálního přístupu lze téhož dosáhnout i následovně:
Map[Function[y,ReplaceAll[y,RuleDelayed[Pattern[x,List[BlankSequence[]]],Last[x]]]],a](* vrátí: {12, p, c, {}} *)
Tento druhý přístup lze přepsat do velmi kompaktního tvaru s použitím syntaktického cukru:
(#/.{x:{__}:>x[[-1]]})&/@a(* vrátí: {12, p, c, {}} *)
Na každý prvek polea je pomocí funkceMap, představované zápisem/@, aplikována ryzí funkce(# /. {x : {__} :> x[[-1]]}) &, jež vezme vstupní parametr, představovaný slotem#, a pomocí funkceReplaceAll, představované zápisem/., provede substituci zadanou předpisemx : {__} :> x[[-1]]. Toto substituční pravidlo nahradí každý výskyt seznamu o alespoň jednom prvku, představovaného výrazem{__} a pojmenovanéhox, jeho posledním prvkem, to jest výrazemx[[-1]].
WL umožňujesymbolické programování, kde s kódem samotným lze nakládat jako s daty. Pro ilustraci uveďme následující příklad, kde je cílem vytvořitvícerozměrné pole, kde dimenzi pole dopředu nevíme a je nechaná jakonezávislá proměnná. Pro konkrétnost mějme funkcif, kterou chceme aplikovat na vícerozměrné pole o dané dimenziD. Toho lze dosáhnout funkcíTable, jejíž syntaxe zní
Table[f[i1,i2,...,iD],{i1,pocatek,konec},{i2,pocatek,konec},...,{iD,pocatek,konec}];
kdei1,i2 atd. jsouindexovací proměnné a kde tři tečky... nejsou součástí kódu, ale pouze naznačují, že je potřeba dodat tolik indexovacích proměnných, kolik má být dimenze výsledného pole. Důležité v tomto ohledu je to, že výše uvedený zápis není jen syntaxí pro funkciTable, ale skutečně výraz tvaruhlavicka[telo], jehož hlavičkou je identifikátorTable a jehož tělo je tvořeno několika prvky, z nichž první má tvarf[i1, i2, ..., iD] a zbylé prvky jsou seznamy. Přitom první prvek každého seznamu je symbol tvarui1,i2, atd., druhý prvekpocatek je celé číslo a třetí prvek každého seznamu je celé číslokonec.
Tato reprezentace kódu umožňuje napsat program, který vytvoří výše zadaný výraz pro libovolnou vstupní dimenzi a rozsah hodnot indexovací proměnné. Pro začátek uvažme dvourozměrné pole, jehož prvky jsoucelá čísla v rozsahu -1 až 1. Následující kód bere jako vstupní proměnné proměnnoudimenze určující dimenzi pole a proměnnépocatek akonec určující rozsah hodnot v každé dimenzi. Výsledek je uložen do proměnnépole:
dimenze=2;pocatek=-1;konec=1;(* vygeneruj indexovací proměnné *)indexy=Symbol["i"<>ToString@#]&/@Range[dimenze](* vrátí: {i1, i2} *)(* pro každou proměnnou specifikuj rozsah hodnot *)rozsahy={#,pocatek,konec}&/@indexy(* vrátí: {{i1, -1, 1}, {i2, -1, 1}} *)(* vlož rozsahy do funkce Table, která vytvoří pole indexací přes dané rozsahy *)pole=Table[f@@indexy,Evaluate[Sequence@@rozsahy]](* vrátí: {{f[-1,-1], f[-1,0], f[-1,1]}, {f[0,-1], f[0,0], f[0,1]}, {f[1,-1], f[1,0], f[1,1]}} *)
Tento kód lze snadno přizpůsobit pro libovolnou jinou dimenzi změnou hodnoty proměnnédimenze (samozřejmě za předpokladu, že funkcef bere více proměnných). Výše uvedený kód tak v podstatě odpovídá posloupnosti vnořenýchfor cyklů, kde počet těchto cyklů není dopředu znám a je určen hodnotou proměnné zadané uživatelem.
Při definici funkce lze kromě samotného těla funkce specifikovat i značné množství dalších prvků, které ovlivňují chování funkce a její zobrazení v editoru. Uvažme funkcif[a,b], jejíž hlavní funkcí je dělit parametra parametremb. Spolu s tím chceme mít možnost nastavit, zda dělení má probíhat standardně čiceločíselně. Pro ilustraci rozšířených možností definice ve WL jsou do následujícího kódu dodány i vzory, které by v reálném případě patrně nebyly potřeba.
(* smaž předchozí definice *)ClearAll[f](* dokumentační a chybová hlášení *)f::usage="Dělení kladného celého čísla";f::invpars="Neplatné vstupy ``, ``.";f::divzero="Dělení nuly nulou.";(* první blok *)SyntaxInformation[f]={"ArgumentsPattern"->{__}};SetAttributes[f,Listable];Options[f]={"Celociselne"->False};Default[f]=2;(* druhý blok *)f[0,0,___]:=Message[f::divzero];Indeterminate;f[x_Integer?NonNegative,y_.,OptionsPattern[]]/;y>0:=Module[{meth=OptionValue["Celociselne"]},If[meth,Quotient[x,y],x/y]]f[x_,y_,___]:=Message[f::invpars,x,y]
Nejprve příkazemClearAll smažeme všechny předchozí definice symboluf, pokud nějaké existovaly. Poté uvedeme dokumentační řetězec a chybová hlášení. Dále specifikujeme, viz sekci kódu "první blok", že se má uživateli v editoru barevně zvýraznit, nenapíše-li žádný vstupní parametr. NastavenímListable jako atribut způsobíme, že při aplikaci funkcef na seznam se tato automaticky aplikuje na jednotlivé prvky. Funkcef má jednu volbu s názvem"Celociselne", udávající, má-li se provést dělení celočíselné či standardní. První blok kódu je zakončen příkazemDefault[f] = 2, který udává, že pokud není dodán vstupní parametr, je automaticky použita hodnota 2.
Druhý blok kódu obsahuje definici samotnou. Nejprve je ošetřen hraniční případ, kdy by mělo dojít k dělení nuly nulou. V takovém případě je vypsána chybová hláška a vrácen předdefinovaný symbolIndeterminate, to jest,neurčité. Poté je dodána hlavní definice, která implementuje dělení vstupních parametrů. Tato definice je zavolána ale pouze tehdy, je-li první parametrnezáporné (NonNegative)celé číslo (Integer) a současně je druhý parametr kladný (y > 0). Pokud jsou tyto podmínky splněny, je nejprve vyvolána hodnota volby"Celociselne" a uložena dolokální proměnnémeth. Je-limeth rovnoTrue, je návratová hodnota výrazuIf rovna výrazuQuotient[x,y]. Tento výraz je vyhodnocen a protože neníIf konstrukt ukončen středníkem, tak je výsledek výpočtuQuotient[x,y] vrácen funkcíf jako jejínávratová hodnota. Pokud jemeth rovnoFalse, probíhá vyhodnocení stejně, akorát je místo funkceQuotient použito reálného dělení.
Konečně, pokud nejsou splněny výše uvedené podmínky na vstupní parametry, je použita poslední část definice na posledním řádku začínající konstruktemf[x_, y_, ___]. Tento konstrukt neobsahuje žádné podmínky a vrací chybové hlášení. Nevyhodnotí se však vždy. Výše uvedená definice nezachycuje např. případy tvaruf[-10]. Takový výraz zůstává nevyhodnocen.
Existuje několik programů sloužících k psaní či alespoň prohlížení kódu a výstupů WL jazyka, přičemž až na jednu výjimku v podobě pluginu proIntelliJ IDEA jsou všechny tyto programy vyvíjené společnostíWolfram Research. Níže je jejich výběr.
WolframKernel čiwolfram v závislosti naoperačním systému[pozn. 12].wolframscript mohou obsahovatshebang, díky nimž z nich lze vUNIXových systémech udělat spustitelný program.Video, jejichžFullForm má tvar normálního výrazu. Zda-li je daný objekt atomárním výrazem lze zjistit pomocí funkceAtomQ.x_ :> x^2.f získat volánímDownValues[f]./. a3->"tři", protože je jinak tento zápis vyhodnocen jako/ 0.3->"tři", to jest dělení výrazem0.3->"tři", což vede k neočekávanému výsledku.-> za předpokladu, že doglobální proměnnéx není uložena žádná hodnota.MathKernel amath.