Programovací jazyk Julia: typový systém, funkce a metody

Pavel Tišnovský 2. 6. 2016

Ve druhé části seriálu o jazyku Julia se budeme zabývat převážně typovým systémem tohoto jazyka, který do značné míry ovlivňuje způsob tvorby programů a mj. umožňuje provádět různé optimalizace a kontroly.

Obsah

1. Programovací jazyk Julia: typový systém, funkce a metody

2. K čemu jsou typy přiřazeny? Zjištění typu hodnoty

3. Základní datové typy v programovacím jazyku Julia

4. Zjištění minimálních a maximálních hodnot základních datových typů, zjištění přesnosti

5. Anotace se specifikací typu

6. Kontrola typů za běhu programu (aserce)

7. Abstraktní datové typy

8. Vytvoření vlastního typu se specifikací jeho bitové šířky

9. Kompozitní datové typy

10. Konstruktory pro kompozitní datové typy

11. Neměnitelné hodnoty (immutable types)

12. Parametrické typy

13. Funkce a metody v programovacím jazyku Julia

14. Odkazy na Internetu

1. Programovací jazyk Julia: typový systém, funkce a metody

V úvodním článku tohoto seriálu jsme se seznámili s některými základními vlastnostmi programovacího jazyka Julia. Připomeňme si, že se jedná o poměrně mladý programovací jazyk, který je primárně určený pro tvorbu jednoúčelových skriptů, ale i rozsáhlých aplikací v oblastech numerické matematiky a statistiky, s čímž poměrně úzce souvisí podpora pro snadné použití nativních knihoven naprogramovaných v jazycích Fortran, C či C++. Programovací jazyk Julia v těchto oblastech konkuruje především projektům R či GNU Octave, částečně taktéž dvojici knihoven Numpy+SciPy společně s Matplotlib (může ovšem někde nahradit i komerční produkty typu Matlab). Julia, ostatně jako většina nově vznikajících jazyků, reflektuje aktuální směr vývoje mikroprocesorů, takže podporuje i paralelní výpočty popř. i distribuci výpočtů mezi několik (i virtuálních) strojů.

Poměrně důležitou součástí programovacího jazyka Julia je jeho typový systém, který je sice dynamický, ovšem v případě potřeby je možné u libovolné hodnoty, parametru funkce či její návratové hodnoty určit její typ způsobem, který známe ze staticky typovaných jazyků. Typový systém je navržen takovým způsobem, že ti programátoři, kteří se jím nechtějí či nepotřebují zabývat, ho mohou prakticky zcela ignorovat a nechat samotný jazyk Julia, ať provádí dynamické určování typů automaticky. Na druhou stranu však znalost typového systému a způsobu deklarace nových typů (včetně typů parametrických) může vést jak k tvorbě efektivnějšího kódu (jak z hlediska nároků na operační paměť, tak i rychlosti výpočtů), tak i k možnostem kontroly chování aplikace v čase jejího běhu (runtime) či k možnosti deklarace chování funkcí na základě typů předávaných parametrů (takové funkce jsou pak realizovány takzvanými metodami, přičemž každá metoda předepisuje chování funkce pro určitou množinu typů parametrů). Právě možnost tvorby vlastních uživatelských typů představuje jednu ze silných zbraní jazyka Julia, i když je samozřejmě možné, že ne všem bude tato vlastnost vyhovovat.

2. K čemu jsou typy přiřazeny? Zjištění typu hodnoty

V programovacím jazyce Julia je informace o typu přiřazena vždy k hodnotě, nikoli nutně k proměnné. Proměnná totiž v tom nejjednodušším případě představuje pouhou vazbu mezi jménem proměnné a konkrétní hodnotou. To mj. znamená, že jedna proměnná může mít v různém čase přiřazenu hodnotu s odlišným datovým typem. Na druhou stranu se ovšem k proměnné může deklarovat aserce kontrolující typ hodnoty, což je systém podobný staticky typovaným programovacím jazykům. Tento koncept je sice logický a pochopitelný, ovšem může způsobovat problémy těm programátorům, kteří přechází například z jazyka Java, kde je koncept typů vlastně převrácený – typ je deklarací přiřazen k proměnným (atributům …) a hodnota přiřazovaná do takové proměnné je konvertována na požadovaný typ a teprve pokud se konverze nedá automaticky provést podle pravidel popsaných ve specifikaci jazyka, je o tom programátor informován.

Pro zjištění typu libovolné hodnoty je možné použít funkci nazvanou typeof():

julia> typeof(42)
Int64
 
julia> typeof(1//3)
Rational{Int64}
 
julia> typeof(pi)
Irrational{:π}
 
julia> typeof(1.2)
Float64
 
julia> typeof(1+2im)
Complex{Int64}
 
julia> typeof(1.2+3im)
Complex{Float64}

Samozřejmě lze tutéž funkci použít i na výrazy, přičemž daný výraz je vyhodnocen (vypočten) a následně je zjištěn typ výsledku. Povšimněte si automatických konverzí u výrazů, v nichž se vyskytují hodnoty různých datových typů:

julia> typeof(1+2)
Int64
 
julia> typeof(1+2//3)
Rational{Int64}
 
julia> typeof(1.2+2//3)
Float64
 
julia> typeof(sin(10))
Float64
 
julia> typeof(true)
Bool
 
julia> typeof(false)
Bool

Typ se zachová i u hodnot typu nekonečno (kladné i záporné) nebo NaN:

julia> typeof(1/0)
Float64
 
julia> typeof(-1/0)
Float64
 
julia> typeof(0/0)
Float64

Tutéž funkci je možné použít i pro proměnné, ovšem jak již víme z předchozího textu, nezjišťuje se typ proměnné (taková informace vlastně neexistuje), ale typ hodnoty spojené v daný okamžik se jménem proměnné:

julia> x=42
42
 
julia> typeof(x)
Int64
 
julia> x=3.14
3.14
 
julia> typeof(x)
Float64
 
julia> x=1//3
1//3
 
julia> typeof(x)
Rational{Int64}
 
julia> x=pi
π = 3.1415926535897...
 
julia> typeof(x)
Irrational{:π}

3. Základní datové typy v programovacím jazyku Julia

Se základními datovými typy jsme se již částečně setkali minule, takže si nyní pouze popišme základní vlastnosti těchto typů:

Jméno Znaménko? Inf NaN Šířka(b) Nejmenší hodnota Nejvyšší hodnota
Bool ne ne ne 8 false true
             
Int8 ano ne ne 8 –27 27 – 1
UInt8 ne ne ne 8 0 28 – 1
Int16 ano ne ne 16 –215 215 – 1
UInt16 ne ne ne 16 0 216 – 1
Int32 ano ne ne 32 –231 231 – 1
UInt32 ne ne ne 32 0 232 – 1
Int64 ano ne ne 64 –263 263 – 1
UInt64 ne ne ne 64 0 264 – 1
Int128 ano ne ne 128 –2127 2127 – 1
UInt128 ne ne ne 128 0 2128 – 1
             
Float16 ano ano ano 16 –65504 65504
Float32 ano ano ano 32 –3.402823 × 1038 3.402823 × 1038
Float64 ano ano ano 64 –1.7 × 10308 1.7 × 10308

Mezi složené datové typy patří Complex64 (dvě hodnoty typu Float32) a Complex128 (dvě hodnoty typu Float64).

4. Zjištění minimálních a maximálních hodnot základních datových typů, zjištění přesnosti

Pro zjištění minimálních a maximálních reprezentovatelných hodnot pro jednotlivé numerické datové typy slouží funkce nazvané typemin() a typemax():

julia> typemin(Int8),typemin(Int16),typemin(Int32),typemin(Int64)
(-128,-32768,-2147483648,-9223372036854775808)
 
julia> typemax(Int8),typemin(Int16),typemin(Int32),typemin(Int64)
(127,-32768,-2147483648,-9223372036854775808)
 
julia> typemin(UInt8),typemin(UInt16),typemin(UInt32),typemin(UInt64)
(0x00,0x0000,0x00000000,0x0000000000000000)
 
julia> typemax(UInt8),typemax(UInt16),typemax(UInt32),typemax(UInt64)
(0xff,0xffff,0xffffffff,0xffffffffffffffff)

Povšimněte si, že se u typů s plovoucí řádovou čárkou (floating point) vrací kladné a záporné nekonečno, nikoli minimální či maximální reprezentovatelná hodnota odlišná od nekonečna (v Javě například Double.MAX_VALUE):

julia> typemin(Float16), typemin(Float32), typemin(Float64)
(-Inf16,-Inf32,-Inf)
 
julia> typemax(Float16), typemax(Float32), typemax(Float64)
(Inf16,Inf32,Inf)

Přesnost (vyjádřenou v počtu bitů mantisy) získáme funkcí precision():

julia> precision(Float16)
11
 
julia> precision(Float32)
24
 
julia> precision(Float64)
53

U celočíselných datových typů nelze tuto funkci použít.

5. Anotace se specifikací typu

V programovacím jazyce Julia je možné použít operátor :: („čtyřtečka“), který dokáže pro hodnotu, výraz, proměnnou, parametr funkce atd. zajistit, že bude skutečně použit vhodný datový typ. Pokud je tento operátor použit společně s proměnnou či parametrem funkce, jedná se vlastně o určitou formu statického typování, i když test, zda typy skutečně odpovídají, je proveden až v čase běhu aplikace (runtime). Podívejme se nejdříve na způsob použití tohoto operátoru pro kontrolu (či spíše aserci), zda je hodnota požadovaného typu:

julia> 1::Int
1
 
julia> 1::Float32
ERROR: TypeError: typeassert: expected Float32, got Int64
 
julia> 1::Bool
ERROR: TypeError: non-boolean (Int64) used in boolean context
 
julia> true::Bool
true
 
julia> true::Int
ERROR: TypeError: typeassert: expected Int64, got Bool

Pozor na nutnost použití závorek u typu „zlomek“ či komplexní číslo:

julia> (1//3)::Rational
1//3
 
julia> (1+2im)::Complex
1 + 2im

6. Kontrola typů za běhu (aserce)

Kontrolu, zda je nějaká hodnota požadovaného datového typu, je možné provést i pro výrazy. Pokud je typ výsledku odlišný, vyhodí se výjimka, pokud však kontrola proběhne v pořádku, vrátí se hodnota vypočteného výrazu. Opět se podívejme na několik testů:

julia> (1+2)::Int8
ERROR: TypeError: typeassert: expected Int8, got Int64
 
julia> (1+2)::Int64
3
 
julia> (1+2)::Int
3
 
julia> (1+2)::Number
3
 
julia> (1//3+1//2)::Number
5//6
 
julia> (1//3+1//2)::Int
ERROR: TypeError: typeassert: expected Int64, got Rational{Int64}

Kontrola se aplikuje ihned po její deklaraci, a to i pro existující hodnotu:

julia> z=0
0
 
julia> z::Int8
ERROR: TypeError: typeassert: expected Int8, got Int64
 
julia> z::Int64
0
 
julia> z=z/2.0
0.5
 
julia> z
0.5
 
julia> z::Int64
ERROR: TypeError: typeassert: expected Int64, got Float64

Ovšem mnohem důležitější je možnost deklarace typů parametrů metody. Jak si řekneme v dalším textu, může se s využitím několika metod implementovat funkce, jejíž chování může být pro různé typy předávaných parametrů odlišné. Nyní se tedy podívejme pouze na velmi jednoduchý příklad, kdy jazyk Julia kontroluje, zda metodě add skutečně předáváme dvě celá čísla se znaménkem:

julia> function add(x::Int, y::Int)
       return x+y
       end
add (generic function with 1 method)

Metodu ihned otestujeme pro různé typy parametrů:

julia> add(1,2)
3
 
julia> add(1,2.0)
ERROR: MethodError: `add` has no method matching add(::Int64, ::Float64)
Closest candidates are:
  add(::Int64, ::Int64)
 
julia> add(1,1//3)
ERROR: MethodError: `add` has no method matching add(::Int64, ::Rational{Int64})
Closest candidates are:
  add(::Int64, ::Int64)

7. Abstraktní datové typy

V programovacím jazyce Julia je možné pracovat i s abstraktími datovými typy, které se nazývají abstraktní z toho důvodu, že není možné vytvářet hodnoty mající tento typ. K čemu jsou tedy abstraktní datové typy užitečné? Umožňují nám vybudovat hierarchii typů, která do určité míry odpovídá hierarchii tříd v objektově orientovaném programování. Každý datový typ (ať již typ konkrétní či abstraktní) totiž může mít svého předka a je tak možné (k čemuž se dostaneme později) například deklarovat metodu akceptující nikoli konkrétní datový typ, ale jeho abstrakci. Příkladem může být například metoda pro výpočet faktoriálu, která by neměla akceptovat libovolný vstup, ale pouze kladná celá čísla reprezentovaná konkrétními typy UInt8, UInt16, UInt32, UInt64 či UInt128. Ovšem celou situaci si můžeme zjednodušit a vytvořit metodu akceptující hodnotu abstraktního datového typu Unsigned, který zahrnuje výše zmíněné odvozené konkrétní datové typy.

Základní hierarchie datových typů programovacího jazyka Julia je sice (i když poněkud nepřesně) popsána v dokumentaci, ovšem pro libovolný typ lze získat informace o jeho předku či potomcích velmi snadno, a to s využitím funkcí nazvaných super() a subtypes(). Podívejme se na použití těchto funkcí:

julia> super(Int32)
Signed
 
julia> super(Signed)
Integer
 
julia> super(UInt8)
Unsigned
 
julia> super(Unsigned)
Integer

Vidíme, že Integer je abstraktní typ, pod nějž spadají celá čísla se znaménkem i bez znaménka. Jaký je jeho nadtyp?:

julia> super(Integer)
Real
 
julia> super(Real)
Number
 
julia> super(Number)
Any
 
julia> super(Any)
Any

Opět vidíme, že na vrcholu hierarchie je typ Any, který je použit implicitně, pokud nestanovíme jinak (tento typ má přibližně 220 podtypů, v závislosti na načtených knihovnách). Zajímavé jsou podtypy abstraktního typu Real:

julia> subtypes(Real)
4-element Array{Any,1}:
 AbstractFloat
 Integer
 Irrational{sym}
 Rational{T<:Integer}

I abstraktního typu Integer a AbstractFloat:

julia> subtypes(Integer)
4-element Array{Any,1}:
 BigInt
 Bool
 Signed
 Unsigned
julia> subtypes(AbstractFloat)
4-element Array{Any,1}:
 BigFloat
 Float16
 Float32
 Float64

8. Vytvoření vlastního typu se specifikací jeho bitové šířky

Zajímavé, mnohdy velmi užitečné a poněkud neobvyklé je, že uživatelé mohou vytvářet své vlastní datové typy odvozené od již existujících numerických typů, přičemž je možné specifikovat bitovou šířku nového datového typu. V současné verzi programovacího jazyka Julia musí být bitová šířka celočíselným násobkem osmi, což je však pochopitelné, především když si uvědomíme, jak jsou numerické hodnoty ukládány do operační paměti. Pro vytvoření nového datového typu uloženého na specifikovaný počet bitů se používá deklarace bitstype vypadající následovně:

bitstype počet_bitů jméno <: nadřazený_typ

Podívejme se, jak se vytvoří nový celočíselný datový typ bez znaménka, který používá 40 bitů (což je násobek osmi):

julia> bitstype 40 UInt40 <: Unsigned

Můžeme si vypsat základní informace o tomto typu:

help?> UInt40
search: UInt40 UInt4 UInt64 uint64
 
  No documentation found.
 
  Summary:
 
  immutable UInt40 <: Unsigned

Potřebujete při výpočtech pracovat s celými čísly se znaménkem o šířce 256 bitů?:

julia> bitstype 256 Int256 <: Signed

Opět si můžeme vypsat základní informace o tomto typu:

help?> Int256
search: Int256
 
  No documentation found.
 
  Summary:
 
  immutable Int256 <: Signed

Pro úplnost si ukažme, jak jsou deklarovány základní numerické datové typy (a boolean), s nimiž jsme se seznámili ve třetí kapitole:

bitstype 16 Float16 <: AbstractFloat
bitstype 32 Float32 <: AbstractFloat
bitstype 64 Float64 <: AbstractFloat
 
bitstype 8  Bool <: Integer
bitstype 32 Char
 
bitstype 8  Int8     <: Signed
bitstype 8  UInt8    <: Unsigned
bitstype 16 Int16    <: Signed
bitstype 16 UInt16   <: Unsigned
bitstype 32 Int32    <: Signed
bitstype 32 UInt32   <: Unsigned
bitstype 64 Int64    <: Signed
bitstype 64 UInt64   <: Unsigned
bitstype 128 Int128  <: Signed
bitstype 128 UInt128 <: Unsigned

9. Kompozitní datové typy

Pod názvem kompozitní datové typy si můžeme představit například struktury (struct) v jazyku C či záznamy (record) z Pascalu. Díky možnostem deklarace nových kompozitních datových typů bylo možné do jazyka Julia přidat nám již známá komplexní čísla (Complex64 a Complex128), ovšem uživatelé si mohou vytvořit libovolné množství dalších podobných typů. Podívejme se na několik jednoduchých příkladů – bude se jednat o takzvané kvaterniony (čtveřice), které jsou zobecněním komplexních čísel:

julia> type Quat
       r
       i
       j
       k
       end
 
help?> Quat
 
  No documentation found.
 
  Summary:
 
  type Quat <: Any
 
  Fields:
 
  r :: Any
  i :: Any
  j :: Any
  k :: Any

Samozřejmě je možné specifikovat i typy jednotlivých položek kompozitního datového typu:

julia> type Quat256
       r::Float32
       i::Float32
       j::Float32
       k::Float32
       end
 
help?> Quat256
search: Quat256
 
  No documentation found.
 
  Summary:
 
  type Quat256 <: Any
 
  Fields:
 
  r :: Float32
  i :: Float32
  j :: Float32
  k :: Float32

10. Konstruktory pro kompozitní datové typy

Způsob vytvoření hodnoty některého ze základních datových typů samozřejmě známe – samotný zápis literálu představuje danou hodnotu (42 apod.). Ovšem v případě kompozitních datových typů je to nepatrně složitější, protože takový typ má větší množství položek, které je nutné inicializovat. Pro tento účel slouží takzvané konstruktory, které jsou vytvořeny automaticky. Přesněji řečeno jsou pro každý typ vytvořeny hned dva konstruktory, přičemž jeden volá funkci convert() pro konverzi svého parametru a druhý akceptuje takový počet parametrů, který odpovídá počtu položek datového typu. Na chvíli se vraťme k námi definovaným typům Quat a Quat256. Instance (objekty) těchto typů lze vytvořit snadno, ovšem povšimněte si toho, že pro stejné parametry získáme odlišné výsledky:

julia> x=Quat(1, 2//3, 3.14, 100000000)
Quat(1,2//3,3.14,100000000)
 
julia> y=Quat256(1, 2//3, 3.14, 100000000)
Quat256(1.0f0,0.6666667f0,3.14f0,1.0f8)

V prvním případě je kompozitní datový typ Quat složen ze čtyř položek typu Any a proto se při konstrukci objektu neprovede žádná konverze. Ve druhém případě jsou položky typu Float32, takže se interpret pokusí o konverzi, která se zde povede. Ovšem někdy konverze není možná, takže interpret při kontrole typů zahlásí chybu:

julia> z=Quat("aa", "bb", "cc", "dd")
Quat("aa","bb","cc","dd")
 
julia> w=Quat256("aa", "bb", "cc", "dd")
ERROR: MethodError: `convert` has no method matching convert(::Type{Float32}, ::ASCIIString)
This may have arisen from a call to the constructor Float32(...),
since type constructors fall back to convert methods.
Closest candidates are:
  call{T}(::Type{T}, ::Any)
  convert(::Type{Float32}, ::Int8)
  convert(::Type{Float32}, ::Int16)
  ...
 in call at none:2

11. Neměnitelné hodnoty (immutable types)

K položkám kompozitních datových typů se přistupuje přes operátor tečky:

julia> x.r=100
100
 
julia> x
Quat(100,2//3,3.14,100000000)
 
julia> x.i
2//3

V některých případech nám však nemusí vyhovovat, že se položky dají měnit stylem proměnná.položka=hodnota. V takových případech je možné kompozitní datový typ deklarovat takovým způsobem, že položky typu nebudou měnitelné (tedy budou immutable). Je to velmi jednoduché, což je patrné z následujícího příkladu:

julia> immutable ImmutableQuat256
       r::Float32
       i::Float32
       j::Float32
       k::Float32
       end
 
julia> q=ImmutableQuat256(1/2, 1/3, 1/4, 1/5)
ImmutableQuat256(0.5f0,0.33333334f0,0.25f0,0.2f0)

Pokus o přečtení položky je validní, ovšem pokus o její přepsání skončí výjimkou:

julia> q.i
0.33333334f0
 
julia> q.i=10
ERROR: type ImmutableQuat256 is immutable

Vidíme, že jediný okamžik, kdy lze zapisovat do položek neměnitelného typu, je konstrukce objektu tohoto typu (to ve skutečnosti není zcela přesné ve chvíli, kdy objekt obsahuje pole, ovšem tímto případem se prozatím nebudeme zabývat).

12. Parametrické typy

Typový systém jazyka Julia by nebyl úplný, pokud by v něm nebyly podporovány parametrické typy. Podívejme se nejdříve na příklad, z něhož bude patrné, jak lze parametrické typy použít a kde mají význam. Jedná se stále o deklaraci typu představujícího kvaternion, ovšem typy položek jsou parametrizovatelné:

julia> type PQuat{T}
       r::T
       i::T
       j::T
       k::T
       end

U takto definovaného kompozitního typu lze určit typ všech položek až při volání konstruktoru, a to například takto:

julia> x=PQuat{Float32}(1, 2, 3, 4)
PQuat{Float32}(1.0f0,2.0f0,3.0f0,4.0f0)
 
julia> y=PQuat{UInt8}(1, 2, 3, 4)
PQuat{UInt8}(0x01,0x02,0x03,0x04)

či dokonce:

julia> z=PQuat{Bool}(1, 0, 1, 0)
PQuat{Bool}(true,false,true,false)

Zde je nutné upozornit na to, že parametr je nedílnou součástí typu (tato informace není zapomenuta), o čemž se lze snadno přesvědčit:

julia> typeof(x)
PQuat{Float32}
 
julia> typeof(y)
PQuat{Bool}

Parametry typu však mohou být i mnohem divočejší, například:

julia> type PPQuat{T1,T2,T3,T4}
       r::T1
       i::T2
       j::T3
       k::T4
       end
 
julia> xx=PPQuat{Int,Any,Float32,Complex128}(42, "ahoj", 3.14, 1+2im)
PPQuat{Int64,Any,Float32,Complex{Float64}}(42,"ahoj",3.14f0,1.0 + 2.0im)
 
julia> typeof(xx)
PPQuat{Int64,Any,Float32,Complex{Float64}}

Povšimněte si, že i Complex je ve skutečnosti parametrickým datovým typem!

13. Funkce a metody v programovacím jazyku Julia

Zajímavé je použití datových typů při tvorbě funkcí. V jazyce Julia může být funkce implementována formou několika metod (minimálně jedné metody), přičemž to, která konkrétní metoda se zavolá, se určí na základě typů předávaných parametrů. Zde je nutné zdůraznit, že tento princip je zobecněním běžných metod známých z OOP, protože tam se konkrétní metoda určuje na základě prvního parametru (this/self). Příklad nyní bude velmi jednoduchý – vytvoříme si funkci pro součet dvou hodnot, přičemž tato funkce bude implementována dvojicí metod. První metoda akceptuje dvě čísla (libovolného typu), druhá metoda akceptuje kvaterniony:

julia> function add(a::Number, b::Number)
       a+b
       end
add (generic function with 1 method)
 
julia> function add(a::Quat256, b::Quat256)
       Quat256(a.r+b.r, a.i+b.i, a.j+b.j, a.k+b.k)
       end
add (generic function with 2 methods)

Nyní si můžeme tyto metody (neboli jedinou funkci add!) otestovat:

widgety

julia> add(x,y)
Quat256(6.0f0,8.0f0,10.0f0,12.0f0)
 
julia> add(1,2)
3
 
julia> add(1//2, 1//3)
5//6

Ovšem podle očekávání následující příkaz neprojde (nebyl by však problém ji dopsat):

julia> add(1//2, x)
ERROR: MethodError: `add` has no method matching add(::Rational{Int64}, ::Quat256)
Closest candidates are:
  add(::Number, ::Number)
  add(::Quat256, ::Quat256)

Typový systém společně s funkcemi/metodami představuje v programovacím jazyku Julia velmi silnou a přitom relativně snadno pochopitelnou techniku, kterou v případě potřeby dokážou využít i lidé, kteří nejsou profesionálními programátory, ale odborníky ve své oblasti (zpracování signálů, numerické výpočty, konstrukce atd.).

14. Odkazy na Internetu

  1. Julia (front page)
    http://julialang.org/
  2. Julia – dokumentace
    http://docs.julialang.org/en/release-0.4/
  3. Julia – repositář na GitHubu
    https://github.com/JuliaLang/julia
  4. Julia (programming language)
    https://en.wikipedia.org/wi­ki/Julia_%28programming_lan­guage%29
  5. IJulia
    https://github.com/JuliaLan­g/IJulia.jl
  6. Introducing Julia
    https://en.wikibooks.org/wi­ki/Introducing_Julia
  7. Julia: the REPL
    https://en.wikibooks.org/wi­ki/Introducing_Julia/The_REPL
  8. Introducing Julia/Metaprogramming
    https://en.wikibooks.org/wi­ki/Introducing_Julia/Meta­programming
  9. Month of Julia
    https://github.com/DataWo­okie/MonthOfJulia
  10. Learn X in Y minutes (where X=Julia)
    https://learnxinyminutes.com/doc­s/julia/
  11. 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
  12. Julia: A Fast Dynamic Language for Technical Computing
    http://karpinski.org/publi­cations/2012/julia-a-fast-dynamic-language
  13. The LLVM Compiler Infrastructure
    http://llvm.org/
  14. Julia: benchmarks
    http://julialang.org/benchmarks/
  15. Type system
    https://en.wikipedia.org/wi­ki/Type_system
  16. Half-precision floating-point format
    https://en.wikipedia.org/wiki/Half-precision_floating-point_format
Našli jste v článku chybu?
Vitalia.cz: Voda z Vltavy před a po úpravě na pitnou

Voda z Vltavy před a po úpravě na pitnou

Lupa.cz: Další Češi si nechali vložit do těla čip

Další Češi si nechali vložit do těla čip

DigiZone.cz: RRTV: frekvence pro Country Radio

RRTV: frekvence pro Country Radio

Lupa.cz: Jak udělat formulář, aby ho vyplnil i negramotný?

Jak udělat formulář, aby ho vyplnil i negramotný?

Měšec.cz: TEST: Vyzkoušeli jsme pražské taxikáře

TEST: Vyzkoušeli jsme pražské taxikáře

Vitalia.cz: Tohle všechno se dá usušit

Tohle všechno se dá usušit

Podnikatel.cz: Udělali jsme velkou chybu, napsal Čupr

Udělali jsme velkou chybu, napsal Čupr

Vitalia.cz: Jak Ondra o astma přišel

Jak Ondra o astma přišel

120na80.cz: Co je padesátkrát sladší než cukr?

Co je padesátkrát sladší než cukr?

DigiZone.cz: DVB-T2 ověřeno: seznam TV zveřejněn

DVB-T2 ověřeno: seznam TV zveřejněn

Vitalia.cz: Muž, který miluje příliš. Ženám neimponuje

Muž, který miluje příliš. Ženám neimponuje

Lupa.cz: Blíží se konec Wi-Fi sítí bez hesla?

Blíží se konec Wi-Fi sítí bez hesla?

Root.cz: Hořící telefon Samsung Note 7 zapálil auto

Hořící telefon Samsung Note 7 zapálil auto

120na80.cz: Galerie: Čínští policisté testují českou minerálku

Galerie: Čínští policisté testují českou minerálku

DigiZone.cz: Parlamentní listy: kde končí PR...

Parlamentní listy: kde končí PR...

Vitalia.cz: dTest odhalil ten nejlepší kečup

dTest odhalil ten nejlepší kečup

Root.cz: Podívejte se na shořelé Samsung Note 7

Podívejte se na shořelé Samsung Note 7

Lupa.cz: Adblock Plus začal prodávat reklamy

Adblock Plus začal prodávat reklamy

Vitalia.cz: Nová vakcína proti chřipce se aplikuje nosem

Nová vakcína proti chřipce se aplikuje nosem

Vitalia.cz: Tradiční čínská medicína a rakovina

Tradiční čínská medicína a rakovina