Hibák előfordulnak. Az Elixirben, bár gyakran mondják, hogy „hagyd összeomlani”, vannak esetek, amikor el kell kapnunk a függvényhívást, hogy egy ismert jó állapotba kerüljünk, és teljesítsünk egy szoftveres szerződést. Egyes nyelvekben a hibákat vezérlési folyamatként használják, az Elixirben azonban ez a minta nem ajánlott. Gyakran pusztán a nevükről felismerhetjük azokat a függvényeket, amelyek hibát dobhatnak: a hibát dobó függvények nevének végén ! áll. Ez szemben áll azokkal a függvényekkel, amelyek {:ok, value} vagy :error értéket adnak vissza. Nézd meg ezeket a könyvtári példákat:
Map.fetch(%{a: 1}, :b)
# => :error
Map.fetch!(%{a: 1}, :b)
# => raises KeyError
Az Elixir egy szerkezetet biztosít a hibák elkapására a try .. rescue segítségével.
try do
raise RuntimeError, "error"
rescue
e in RuntimeError -> :error
end
Vizsgáljuk meg ezt a szerkezetet:
try kulcsszóval deklaráljuk.raise/2 függvényt hívjuk.rescue részben a dobott hiba modul nevére illesztünk mintát
-> bal oldalán:
e a hibastruktúrához illeszkedik.in egy kulcsszó.RuntimeError az a hiba, amelyet el akarunk kapni.
_-t használhatnánk a modulnév helyett, vagy teljesen elhagyhatnánk az in kulcsszót.A hibák (amelyeket néha „kivételeknek” is neveznek), amelyeket így elkapunk, struktúrák. Az Elixirben a hibák elkapása nagyon ritkán fordul elő. Általában az elkapott hibát naplózzák vagy egy külső monitorozó szolgáltatásnak küldik, majd újra dobják. Ez azt jelenti, hogy általában nem foglalkozunk az adott hibastruktúra belső szerkezetével.
A Kivételek fogalom oldalon többet megtudhatsz a hibastruktúrákról, többek között arról, hogyan definiálhatsz saját egyedi hibát.
Az Instruments of Texas-nál dolgozva az a feladatod, hogy egy kísérleti, fordított lengyel jelölésű [RPN] számológépen dolgozz, amely Elixirben íródott. A csapatodnak az okoz gondot, hogy néhány művelet hibát dob, és emiatt összeomlik a folyamat. Az a feladatod, hogy írj egy függvényt, amely becsomagolja a műveletvégző függvényt, hogy a hibákat elegánsabban lehessen kezelni idiomatikus Elixir-kóddal.
Valósítsd meg a calculate!/2 függvényt úgy, hogy meghívja a műveletfüggvényt, egyetlen argumentumként a vermet adva át neki. A műveletfüggvény máshol van definiálva, de tudod, hogy vagy sikeresen lefut, vagy hibát dob.
stack = []
operation = fn _ -> :ok end
RPNCalculator.calculate!(stack, operation)
# => :ok
stack = []
operation = fn _ -> raise ArgumentError, "An error occurred" end
RPNCalculator.calculate!(stack, operation)
# => ** (ArgumentError) An error occurred
A
!-ra végződő függvénynevek arra figyelmeztetik a programozókat, hogy ez a függvény hibát dobhat
Ahogy jobban utánanézel, észreveszed, hogy sok függvény atomokkal és tuple-okkal jelzi a sikerét vagy a kudarcát. Valósítsd meg a calculate/2 függvényt ezzel a stratégiával.
stack = []
operation = fn _ -> "operation completed" end
RPNCalculator.calculate(stack, operation)
# => {:ok, "operation completed"}
stack = []
operation = fn _ -> raise ArgumentError, "An error occurred" end
RPNCalculator.calculate(stack, operation)
# => :error
Néhány hiba fontos információt tartalmaz, amire a kollégáidnak szüksége van ahhoz, hogy a rendszer helyesen működjön. Valósítsd meg a calculate_verbose/2 függvényt, hogy továbbadja a hibaüzenetet. A hiba egy struktúra, amelynek van egy :message mezője.
stack = []
operation = fn _ -> "operation completed" end
RPNCalculator.calculate_verbose(stack, operation)
# => {:ok, "operation completed"}
stack = []
operation = fn _ -> raise ArgumentError, "An error occurred" end
RPNCalculator.calculate_verbose(stack, operation)
# => {:error, "An error occurred"}
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Elixir nyelvet 58 fogalom168 feladat segítségével, valódi emberi mentorálással, mindez ingyen.