Kurzusok
/
Julia
Julia
/
Feladatok
/
Osztályozó guru
Osztályozó guru

Osztályozó guru

Tanulófeladat

Bevezetés

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.

  1. A Juliának vannak types, amelyek központi szerepet játszanak a tervezésében.
  2. A Julia általában „kitalálja” a típust, 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.

Típus-hozzárendelés

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:

  • Kis szkriptekben nagyon kényelmes.
  • Nagyobb programokban árt a teljesítménynek és a megbízhatóságnak.

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.

A típus-hierarchia

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:

  • Az Int16 egy típus, és létrehozhatunk ilyen típusú változókat.
  • Az Int16 a Signed altípusa, és ezt a supertype() függvény mutatja meg nekünk.
  • Létezik a típusoknak egy hierarchiája, amely az 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.

Típusvizsgálat

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

Absztrakt és konkrét típusok

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:

  1. Az altípusokkal rendelkező csomópontokat abstract-nak nevezzük.
  2. A levélcsomópontokat, amelyeknek nincs altípusuk, 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.

Utasítások

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.

  • Egyes professzorok valós számokat használnak (mert a pontosság megszállottjai), és ezeket UInt8 adattípussá kell alakítanod.
  • Más professzorok negatív előjelű egészeket használnak (hogy megbüntessék a különösen fegyelmezetlen tanulókat), és ilyenkor ezeket 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.

  • Egyes professzorok növekvő sorrendbe rendezett Vector-okat használnak a jegyeik tárolására, mert rendkívül precízek az adataikkal.
  • Más professzorok rendezetlen 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.

Note

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

1. Csökkentsd a jegyeket

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.
  • Tetszőleges Integer esetén ugyanazt az egészet kell visszaadnia Int8 adattípusban.
  • Minden más bemenet esetén MethodError-t kell dobnia.
julia> demote(4.2)::UInt8
5

julia> demote(4)::Int8
4

julia> demote("hi")
MethodError: no method matching demote(::String)     #output truncated

2. Dolgozd fel előre az adatokat

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.
  • Minden más bemenet esetén MethodError-t kell dobnia.
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
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Julia Exercism

Készen állsz elkezdeni a(z) Osztályozó guru feladatot?

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.