A tanterv eddig nem sokat mondott a típusokról, de nyilvánvalóan léteznek a Juliában:
julia> vals = (42, 4.3, π, "hello", 'Q')
(42, 4.3, π, "hello", 'Q')
julia> typeof(vals)
Tuple{Int64, Float64, Irrational{:π}, String, Char}
Sosem adtuk meg a típusokat, a Julia mégis hozzárendelte őket.
types, amelyek központi szerepet játszanak a tervezésében.Type Inference segítségével.A JIT-fordító átnézi az (összes) kódot, megnézi, hogyan használjuk a változót, és kikövetkeztet egy olyan megfelelő alapértelmezett típust, amely összeegyeztethető ezzel a használattal.
A típuskövetkeztetésre hagyatkozni rendben van egyszerű gyakorlófeladatok megoldásánál, de nagyobb programoknál valószínűleg pontosabb irányításra lesz szükséged.
A legtöbb modern processzoron egy egész szám alapértelmezett típusa az Int64.
A Numbers fogalomban láttuk, hogy egy érték átalakítható egy adott, nem alapértelmezett típusra.
julia> x = Int16(42)
42
julia> typeof(x)
Int16
Az x változó azonban továbbra is hozzárendelhető egy másik típushoz:
julia> x = "changed"
"changed"
julia> typeof(x)
String
Ez a type instability, ami:
Ehelyett a :: operátorral megadhatjuk az x típusát:
julia> y::Int16 = 42
42
julia> typeof(y)
Int16
julia> y = "changed"
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int16
The function `convert` exists, but no method is defined for this combination of argument types.
Mostantól y Int16 típusú, és az is marad.
Így a fordító tudja, hány bájtot kell fenntartania számára, és a kód többi részét is optimalizálhatja arra, hogy egy stabil típusra támaszkodjon.
Ebben a változó többé-kevésbé hasonlít egy statikusan típusos nyelv, például a C változóihoz.
Int64, Int16, String, Char: honnan „származnak” ezek a típusok?
Sok objektumorientált (OO) nyelvben minden típus egy osztály, az alosztályozás osztályhierarchiába rendezi őket, és az osztálymetódusok határozzák meg a viselkedést.
A Java és a Ruby nyilvánvaló példák erre a mintára, de még a Python is hasonlóan működik belül.
A Juliának nincsenek osztályai.
A dokumentált ok az, hogy az OO-jellemzők zavarják a JIT-fordítót, és rontják a futásidejű teljesítményt.
És mégis, nézd meg ezt a kódot:
julia> y::Int16 = 42
42
julia> typeof(y)
Int16
julia> supertype(Int16)
Signed
julia> supertypes(Int16)
(Int16, Signed, Integer, Real, Number, Any)
Kiegészítésképpen néhány részlet:
Int16 egy típus, és létrehozhatunk ilyen típusú változókat.Int16 a Signed altípusa, és ezt a supertype() függvény mutatja meg nekünk.Integer, Real és Number szinteken keresztül halad felfelé a legfelső Any-ig, és a subtypes() függvény kilistázza nekünk a hierarchia ezen ágát.Minden ág az Any-ban végződik, amely egyedülálló abban, hogy a saját szupertípusa.
julia> supertypes(String)
(String, AbstractString, Any)
julia> supertype(Any)
Any
Tehát a Juliának nincs class-hierarchiája, de van type-hierarchiája.
Egyszer majd megpróbáljuk kibogozni, hogyan is működik ez, de előbb még sokkal többet kell felfedeznünk.
A typeof() függvénnyel a szokásos módon vizsgálhatjuk az egyenlőséget.
julia> typeof(11)
Int64
julia> typeof(11) == Int64
true
julia> typeof(11) == Number
false
A típusegyenlőségnek pontosnak kell lennie, mert ez az összehasonlítási forma mit sem tud a típus-hierarchiáról.
Rugalmasabban az isa megmondja, hogy egy érték ugyanolyan típusú-e, mint az összehasonlító, vagy annak egy altípusa-e.
Használható függvény- vagy infix alakban is.
julia> 12 isa Int64
true
julia> 12 isa Number
true
julia> isa(12, Number)
true
julia> 12 isa String
false
Vedd figyelembe, hogy az isa a bal oldalon value-t vár, nem type-ot.
Ha két típust próbálunk így összehasonlítani, váratlan eredményt kapunk.
A helyes operátor a <:, amellyel a későbbi fogalmakban még sokat fogunk találkozni.
julia> Int64 isa Number ## Don't do this!
false
julia> Int64 <: Number
true
Láttuk, hogy a típus-hierarchia fastruktúrát alkot (a számítástudomány értelmében, a gyökérrel a tetején).
A fa minden eleme egy node, és ezeket kategóriákba sorolhatjuk:
abstract-nak nevezzük.concrete-nak nevezzük.julia> subtypes(Integer) # an abstract type
3-element Vector{Any}:
Bool
Signed
Unsigned
julia> subtypes(Int64) # a concrete type
Type[]
Ez fontos megkülönböztetés, mert változóként csak konkrét típusokat lehet instantiated-ni.
julia> a::Int16 = 42
42
julia> typeof(a)
Int16
julia> b::Integer = 42
42
julia> typeof(b)
Int64
Vedd figyelembe, hogy ha absztrakt típust próbálunk használni, (ebben az esetben) nem kapunk hibaüzenetet, de a fordító létrehoz egy megfelelő konkrét típust: Integer helyett Int64-et.
Ebben a feladatban egy kis adatmérnöki munkát végzel: előfeldolgozol néhány osztályozási adatot. Egy iskola, ahová nagyon, nagyon, nagyon sok (talán túl sok?) tanuló jár, adatelemzést szeretne végezni a tanulók jegyein, méghozzá hatékonyan, ezért az a cél, hogy az adatokat minimalizálja és rendszerezze.
Az osztályozási skála általában 0-tól 10-ig terjed, ezért a leghatékonyabb olyan adattípust használni, amelyben jegyenként csupán nyolc bit van.
UInt8 adattípussá kell alakítanod.Int8 adattípussá kell alakítanod.Miután megvalósítottad a jegyek átalakítására szolgáló függvényt, írnod kell egy másikat is, amely a jegyeket tároló gyűjteményeket kezeli: lecsökkenti a jegyeket, és csökkenő sorrendben adja vissza őket.
Vector-okat használnak a jegyeik tárolására, mert rendkívül precízek az adataikkal.Set-eket használnak a jegyeik tárolására, mert egy kicsit lustábbak.Mindkét függvényben kezelned kell az érvénytelen bemeneteket úgy, hogy MethodError-t dobj.
A kivételkezeléssel egy későbbi fogalomban fogsz találkozni, ezért ebben a feladatban egyelőre a következő szintaxist használhatod:
throw(MethodError(f, args))
Ahol f a függvény, args pedig a függvénynek átadott argumentumokat tartalmazó tuple.
A demote(n) függvény esetében f a demote, args pedig (n,):
throw(MethodError(demote, (n,)))
Valósítsd meg a demote(n) metódust.
Float64 bemenet esetén felfelé kell kerekítenie a legközelebbi egész számra, és UInt8 adattípust kell visszaadnia.Integer esetén ugyanazt az egészet kell visszaadnia Int8 adattípusban.julia> demote(4.2)::UInt8
5
julia> demote(4)::Int8
4
julia> demote("hi")
MethodError: no method matching demote(::String) #output truncated
Valósítsd meg a preprocess(coll) metódust.
Vector bemenet esetén le kell csökkentenie az összes számot, és meg kell fordítania a vektort.Set bemenet esetén le kell csökkentenie az összes számot, és egy csökkenő sorrendbe rendezett vektort kell visszaadnia.julia> preprocess([1, 2, 3])
3-element Vector{Int8}:
3
2
1
julia> preprocess(Set([2.2, 5.8, 3.4]))
3-element Vector{UInt8}:
6
4
3
julia> preprocess(42)
MethodError: no method matching preprocess(::Int64) #output truncated
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Julia nyelvet 35 fogalom128 feladat segítségével, valódi emberi mentorálással, mindez ingyen.