A tuple véges, rendezett elemlista, amely változtathatatlan. A tuple-oknál minden pozíciónak kötött típusúnak kell lennie. Ez pedig azt jelenti, hogy a fordító tudja, melyik pozíción milyen típus áll. A tuple-ban használt típusok pozíciónként eltérőek lehetnek, de a típusokat fordítási időben ismerni kell.
Attól függően, hogy a tuple értékeinek típusai lefordíthatók-e, a tuple többféleképpen hozható létre. Ha az értékek fordítási időben ismertek, a tuple a tuple literál szintaxisával hozható létre, ellenkező esetben explicit módon kell deklarálni őket. Az is fontos, hogy az értékek típusai egyezzenek a tuple-ban megadott típusokkal, és hogy az értékek száma megegyezzen a megadott típusok számával. Íme egy példa a tuple literál szintaxissal történő definiálásra:
tuple = {1, "foo", 'c'} # Tuple(Int32, String, Char)
Lehetőség van arra is, hogy egy tuple-t a Tuple osztály segítségével hozz létre.
tuple = Tuple(Int32, String, Char).new(1, "foo", 'c')
Vagy explicit módon megadhatod a tuple-hoz rendelt változó típusát.
tuple : Tuple(Int32, String, Char) = {1, "foo", 'c'}
A tuple típusának explicit megadása azért lehet hasznos, mert így megadhatod, hogy egy pozíció uniótípust tartalmazzon. Ez azt jelenti, hogy egy pozíció több típust is tartalmazhat.
tuple : Tuple(Int32 | String, String, Char) = {1, "foo", 'c'}
Egy tömbből a Tuple osztály from metódusával hozhatsz létre tuple-t.
Ehhez meg kell adni a tuple típusát.
array = [1, "foo", 'c']
tuple = Tuple(Int32, String, Char).from(array)
Egy tuple-t a to_a metódussal konvertálhatsz tömbbé.
Az így kapott tömb elemtípusa a tuple egyes mezői típusainak uniója.
tuple = {1, "foo", 'c'}
array = tuple.to_a
array # => [1, "foo", 'c']
A tömbökhöz hasonlóan a tuple-ok indexelése nullától indul, vagyis az első elem a 0. indexen van.
A tömböktől eltérően azonban az egyes elemek típusa rögzített, és fordítási időben ismert, ezért egy tuple indexelésekor az elem típusa a pozíciótól függ.
Egy tuple elemének eléréséhez a [] operátort használhatod.
array = [1, "foo", 'c']
array[0] # => 1
typeof(array[0]) # => Int32 | String | Char
tuple = {1, "foo", 'c'}
tuple[0] # => 1
typeof(tuple[0]) # => Int32
További különbség a tömbök elemeinek eléréséhez képest, hogy ha az index meg van adva, a fordító ellenőrzi, hogy az index a tuple határain belül van-e. Ez azt jelenti, hogy futásidejű hiba helyett fordítási idejű hibát kapsz.
tuple = {1, "foo", 'c'}
tuple[3]
# => Error: index out of bounds for Tuple(Int32, String, Char) (3 not in -3..2)
Ha viszont az index egy változóban van tárolva, a fordító fordítási időben nem tudja ellenőrizni, hogy az index a tuple határain belül van-e, és ilyenkor futásidejű hibát kapsz.
Egy tuple résztuple-ját a [] operátorral és egy tartománnyal kaphatod meg.
A visszatérési érték egy új tuple, amely a megadott tartomány elemeit tartalmazza.
A tartományt fordítási időben kell megadni, különben a fordító nem tudja meghatározni a résztuple elemeinek típusait.
Ez azt jelenti, hogy a tartománynak tartomány literálnak kell lennie, és nem lehet változóhoz rendelve.
tuple = {1, "foo", 'c'}
subtuple = tuple[0..1] # Tuple(Int32, String)
i = 0..1
tuple[i]
# Error: Tuple#[](Range) can only be called with range literals known at compile-time
A tuple-ok akkor hasznosak, ha fix számú értéket szeretnél egy csoportba foglalni, és az értékek típusai fordítási időben ismertek. Ennek az az oka, hogy a tuple-ok kevesebb memóriát igényelnek, és a változtathatatlanságuk miatt gyorsabbak a tömböknél. Egy másik felhasználási eset, amikor egy metódus több értéket ad vissza. Ez különösen akkor hasznos, ha az értékek típusa eltérő, hiszen a tuple minden pozíciója más típusú lehet.
Ne használj tuple-t olyankor, amikor olyan adatszerkezetre van szükség, amely méretében nőhet vagy csökkenhet, vagy amelyet gyakran kell módosítani.
A szimbólumok névvel ellátott azonosítók, amelyekkel egy értékre hivatkozhatsz.
A szimbólumok szimbólum literál segítségével jönnek létre, mégpedig úgy, hogy egy név elé egy : karaktert írsz, például :foo.
Lehetőség van arra is, hogy idézőjelek között írd le őket, például :"foo" alakban, amivel például szóköz is szerepelhet a névben.
:foo # => :foo
:"foo boo" # => :"foo boo"
:foo == :"foo" # => true
A szimbólumokat a nyelv számos helyén használják, többek között namedtuple-ok kulcsaiként, valamint metódusok és változók neveinek jelölésére.
A szimbólumok a Crystalben egészen mások, mint a Rubyban. A Crystalben a szimbólum egyfajta konstans, ezért fordítási időben jön létre. Ez azt jelenti, hogy a szimbólumok nem hozhatók létre dinamikusan, ami a Rubyban lehetséges.
A Crystalben a szimbólumok Int32-ként vannak reprezentálva, ami nagyon hatékonnyá teszi őket.
A szimbólumokat át lehet alakítani stringgé, de fordítva nem. Ennek az az oka, hogy a szimbólumok fordítási időben, a stringek pedig futásidőben jönnek létre.
:foo.to_s # => "foo"
Amikor épp sütiket készülsz sütni a barátaidnak, rájössz, hogy a receptben szereplő néhány mértékegységet át kell váltanod. Mivel csak a metrikus rendszert ismered, ki kell találnod egy módot arra, hogy a gyakori amerikai sütési mértékegységeket milliliterre (mL) váltsd a saját könnyebbségedre.
Használd ezt az átváltási táblázatot a megoldásodhoz:
| Átváltandó mértékegység | térfogat | milliliterben (mL) |
|---|---|---|
| mL | 1 | 1 |
| amerikai csésze | 1 | 240 |
| amerikai folyékony uncia | 1 | 30 |
| amerikai teáskanál | 1 | 5 |
| amerikai evőkanál | 1 | 15 |
Mivel tehetséges programozótanonc vagy, úgy döntesz, hogy a millilitert átmeneti mértékegységként használod, hogy könnyebben átválthass bármelyik felsorolt mértékegységről bármelyik másikra (még önmagára is).
Valósítsd meg a KitchenCalculator.get_volume metódust.
Egy térfogatpár tuple esetén csak a numerikus komponenst kell visszaadnia.
KitchenCalculator.get_volume({:cup, 2.0})
# => 2.0
Valósítsd meg a KitchenCalculator.to_milliliter metódust.
Egy térfogatpár tuple esetén a térfogatot milliliterre kell váltania az átváltási táblázat segítségével.
KitchenCalculator.to_milliliter({:cup, 2.5})
# => {:milliliter, 600.0}
Valósítsd meg a KitchenCalculator.from_milliliter metódust.
Egy térfogatpár tuple és a kívánt mértékegység esetén a térfogatot a kívánt mértékegységre kell váltania az átváltási táblázat segítségével.
KitchenCalculator.from_milliliter({:milliliter, 1320.0}, :cup)
# => {:cup, 5.5}
Valósítsd meg a KitchenCalculator.convert metódust.
Egy térfogatpár tuple és a kívánt mértékegység esetén a megadott térfogatot a kívánt mértékegységre kell váltania.
KitchenCalculator.convert({:teaspoon, 9.0}, :tablespoon)
# => {:tablespoon, 3.0}
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Crystal nyelvet 26 fogalom142 feladat segítségével, valódi emberi mentorálással, mindez ingyen.