A rekordok olyan adatszerkezetek, amelyek címkékkel csoportosítják az összetartozó információkat. Hasonlítanak a JavaScript vagy Java objektumaihoz, illetve a C vagy Rust structjaihoz, de néhány lényeges különbség van köztük.
A rekordokat kapcsos zárójelekkel hozzuk létre, az elemeiket pedig vessző választja el.
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
A rekord típusát is hasonló szintaxissal definiáljuk, azzal a különbséggel, hogy az egyenlőségjeleket (=) kettőspontok (:) helyettesítik.
firefly : { name : String, creator : String, episodes : Int }
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
Ezeket a típusdefiníciókat ismételgetni körülményes, ezért gyakori megoldás, hogy egy típusalias segítségével megosztjuk a definíciót.
type alias TvSeries =
{ name : String
, creator : String
, episodes : Int
}
firefly : TvSeries
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
A típusalias emellett automatikusan biztosít egy konstruktorfüggvényt is a rekordhoz. Ez néha meglepő, hiszen az Elmben a függvényeknek kisbetűvel kell kezdődniük, a típuskonstruktorok viszont ez alól kivételt képeznek.
firefly : TvSeries
firefly = TvSeries "Firefly" "Joss Whedon" 14
A legfőbb módja annak, hogy hozzáférjünk egy rekordpéldány egyik mezőértékéhez, a pontjelölés használata, például így: firefly.creator.
Az Elm fordító emellett támogat olyan speciális elérési függvényeket is, amelyek ponttal (.) kezdődnek, például a .creator, és minden olyan rekordon működnek, amelyben van ilyen nevű mező.
Ez a második kivétel az alól a szabály alól, hogy a függvényeknek kisbetűvel kell kezdődniük.
Valójában a felhasználó által definiált függvényeknek kisbetűvel kell kezdeniük, de az imént megismert két példát a fordító generálja, nem a programozó.
firefly : TvSeries
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
firefly.name
--> "Firefly"
.creator firefly
--> "Joss Whedon"
A rekordokat kötéseken belül destrukturálhatjuk is a rekordok mintaillesztésével. A destrukturálás bármely olyan rekordon működik, amelyben megvannak a szóban forgó nevű mezők.
episodesCount : TvSeries -> Int
episodesCount { episodes } =
episodes
complicatedCopy : TvSeries -> TvSeries
complicatedCopy show =
let
{ name, creator } = show
in
{ name = name
, creator = creator
, episodes = episodesCount show
}
A rekordok változtathatatlanok, ahogy az Elmben minden, így ha egyszer definiáltunk egy rekordot, a mezőértékei soha nem változhatnak meg.
Létezik egy speciális szintaxis, amellyel egy meglévő rekord másolatát hozhatjuk létre úgy, hogy egy vagy több mezőjét megváltoztatjuk.
Ez a szintaxis a pipe (|) szimbólumot használja, hogy megkülönböztesse az eredeti rekordot a megváltozó mezőktől, például így: { oldRecord | field1 = newValue }.
firefly : TvSeries
firefly =
{ name = "Firefly"
, creator = "Joss Whedon"
, episodes = 14
}
updatedFirefly : TvSeries
updatedFirefly =
{ firefly | creator = "J Whedon", episodes = 15 }
Az Elm [szerkezeti egyenlőséget][equality] használ, ami azt jelenti, hogy ugyanazon rekord két példánya azonos értékekkel egyenlő.
firefly1 = TvSeries "Firefly" "Joss Whedon" 14
firefly2 = TvSeries "Firefly" "Joss Whedon" 14
firefly1 == firefly2
--> True
Az Elm a szerkezeti típusozást is támogatja, ami azt jelenti, hogy ha egy függvény olyan rekordot vár, amelyben van x és y mező, akkor bármely olyan rekordon működik, amelyben megvannak ezek a mezők, például kétdimenziós pontokon, háromdimenziós pontokon, űrhajókon stb.
Ezeknek a rekordtípusoknak a definíciójában szerepel egy pipe (|), például { a | x : Float, y : Float }, és az Elm terminológiájában „bővíthető rekordoknak” nevezzük őket.
Ügyelj a különbségre egy típusdefinícióban szereplő pipe (|) között, amely egy bővíthető rekord definíciója ({ a | x : Int }), és egy tényleges rekordpéldányban szereplő pipe (|) között, amely azt jelenti, hogy a rekord néhány mezőjét frissítjük.
point2d = { x = 1, y = 2 }
point3d = { x = 3, y = 4, z = 7 }
.x point2d --> 1
.x point3d --> 3
length : { a | x : Float, y : Float } -> Float
length vector =
sqrt (vector.x * vector.x + vector.y * vector.y)
length point2d --> 2.236068
length point3d --> 5
translateX : { a | x : Float } -> { a | x : Float }
translateX vector =
{ vector | x = vector.x + 1 }
translateX point2d --> { x = 2, y = 2 }
translateX point3d --> { x = 4, y = 4, z = 7 }
Ebben a feladatban nagy sportrajongó vagy, és épp most fedeztél fel magadban szenvedélyt az NBA kosárlabda iránt. Mivel még új vagy az NBA kosárlabdában, mélyelemzést végzel az NBA történetéből: nyomon követed a csapatokat, az edzőket és a győzelmi/vereség statisztikáikat, és összehasonlítod őket egymással.
Mivel még nincs kedvenc csapatod, egy algoritmust is fejlesztesz majd, amivel eldöntheted, hogy egy adott csapatnak szurkolj-e. Hét részfeladat segít abban, hogy kifejleszd a saját csapatszurkolási algoritmusodat.
Definiáld a Coach típusaliast egy rekordhoz a következő két mezővel, a következő sorrendben:
name: az edző neve, típusa String.formerPlayer: jelzi, hogy az edző korábban játékos volt-e, típusa Bool.Definiáld a Stats típusaliast egy rekordhoz a következő két mezővel, a következő sorrendben:
wins: a győzelmek száma, típusa Int.losses: a vereségek száma, típusa Int.Definiáld a Team típusaliast egy rekordhoz a következő három mezővel, a következő sorrendben:
name: a csapat neve, típusa String.coach: a csapat edzője, típusa Coach.stats: a csapat statisztikái, típusa Stats.Olyan harmadik féltől származó kóddal szeretnél együttműködni, amelynek van egy csapat fogalma, de más sorrendben hívja meg a kódodat a paraméterekkel. Adj hozzá egy createTeam függvényt a következő szignatúrával: String -> Stats -> Coach -> Team.
Mivel az NBA-tulajdonosok türelmetlenek, rájöttél, hogy a rossz csapateredmények gyakran az edző lecseréléséhez vezetnek.
Valósítsd meg a replaceCoach függvényt, amely paraméterként az új edzőt és a csapatot kapja, és visszaadja a csapatot, de az új edzővel:
let
coach = { name = "Larry Bird", formerPlayer = True }
stats = { wins = 58, losses = 24 }
team = { name = "Indiana Pacers", coach = coach, stats = stats }
newCoach = { name = "Isiah Thomas", formerPlayer = True }
in
replaceCoach newCoach team
--> { name = "Indiana Pacers"
-- , coach = { name = "Isiah Thomas", formerPlayer = True }
-- , stats = { wins = 58, losses = 24 } }
A jövőben egy bonyolult algoritmust tervezel kidolgozni arról, hogy szurkolj-e egy csapatnak vagy sem, de első próbálkozásként úgy döntöttél, hogy minden olyan csapatnak szurkolsz, amelynek több győzelme van, mint veresége.
Szeretnéd, ha ez a függvény más helyzetekben is újrahasznosítható lenne, ezért használj kiterjeszthető rekordot a típus szignatúrában, hogy bármilyen rekordot elfogadjon, amely rendelkezik a szükséges mezőkkel.
Hogy a függvény a lehető legtömörebb legyen, mintázatillesztéssel szeretnéd kinyerni a stats mezőt a függvény paraméteréből.
Valósítsd meg a rootForTeam függvényt, amely egy csapatot kap, és True értéket ad vissza, ha szurkolni kell a csapatnak; egyébként False értéket ad vissza.
let
spursCoach = { name = "Gregg Popovich", formerPlayer = False }
spursStats = { wins = 56, losses = 26 }
spursTeam = { name = "San Antonio Spurs", coach = spursCoach, stats = spursStats }
in
rootForTeam spursTeam
--> True
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Elm nyelvet 28 fogalom110 feladat segítségével, valódi emberi mentorálással, mindez ingyen.