Niepowodzenia bywają przerażające, ale są istotną częścią programowania. Niepowodzenia można wykorzystać do nauki debugowania, wyszukiwania ograniczeń programu lub błyskawicznego sprawdzania, czego nie należy robić!
Nie ma nic złego w niepowodzeniach
W Verse niepowodzenie ma specyficzne znaczenie. Nie zawsze oznacza ono, że coś nie działa. Jest ono sposobem sterowania działaniem programu.
Pamiętasz, jak w lekcji 4 była mowa o tym, że możesz napisać kod w celu zadania pytania tak lub nie?
var Tired: logic = false
var WhatToWatch: string = “nic”
if (Tired?):
set WhatToWatch = “własne powieki od spodu”
else:
set WhatToWatch = “kreskówki”
Print(“Obejrzyj {WhatToWatch}”)
# Obejrzyj kreskówki
Kod zadający to pytanie zapisuje się jako wyrażenie zawodne. W powyższym przykładzie Tired? jest wyrażeniem zawodnym.
Wyrażenia zawodne pozwalają unikać błędów, które mogłyby spowodować, że program całkowicie przestanie działać. Wiemy na przykład, że dzielenie przez zero jest niemożliwe. Gdyby podjąć próbę uwzględnienia takiego dzielenia w kodzie, mógłby on ulec awarii! Jednak poniższy kod Verse zostanie wykonany prawidłowo.
if (5/0):
Print("Hola, hola!")
else:
Print("Nie da się tego zrobić!")
Aby uniknąć tego rodzaju błędów, Verse wymaga zapisywania wyrażeń zawodnych w kontekście niepowodzenia. Konteksty niepowodzenia stwarzają dla wyrażeń zawodnych bezpieczne otoczenie, w którym mogą okazywać się one zawodne. W powyższym przykładzie 5/0 było wyrażeniem zawodnym, a if() stanowiło kontekst niepowodzenia. W dalszej części artykułu dowiesz się więcej na temat obydwu tych pojęć w Verse.
Wyrażenia zawodne
W Verse istnieje wiele sposobów pisania wyrażeń zawodnych. Jeśli wyrażenie zadaje pytanie typu tak lub nie, prawdopodobnie jest ono zawodne.
Oto kilka rodzajów pytań zadawanych za pomocą wyrażeń zawodnych:
- Czy jedna z tych dwóch zmiennych jest większa lub mniejsza od drugiej lub czy te dwie zmienne są takie same?
- Czy ta zmienna ma ustawioną wartość
true? - Czy dla tej zmiennej ustawiono wartość?
- Czy to wyrażenie powoduje błąd?
Jeśli odpowiedź na dowolne z tych pytań brzmi tak, wyrażenie zwraca powodzenie. Jeśli odpowiedź brzmi nie, wyrażenie zwraca niepowodzenie. To, co stanie się po zwróceniu powodzenia lub niepowodzenia, zależy od tego, jak napiszesz kod.
Wyrażenia porównawcze
Wyrażenia porównawcze, w których wykorzystuje się takie operatory porównawcze, jak < (mniejsze niż), > (większe niż) lub <> (różne od), są wyrażeniami zawodnymi. W poniższym przykładzie 5 < 4 jest wyrażeniem zawodnym, które zwróci niepowodzenie:
if (5 < 4):
Print(“To nigdy nie zostanie wyświetlone.”)
Wyrażenie 5 < 4 oznacza pytanie, “czy 5 jest mniejsze niż 4?”. Odpowiedź brzmi nie, wyrażenie zwraca niepowodzenie, a blok kodu (zapisany z wcięciem pod wyrażeniem if) nie zostaje uruchomiony.
Przyjrzyjmy się zatem kolejnemu przykładowi z wyrażeniem zawodnym MousetrapsSet <> MiceCaught. Oznacza ono pytanie: “Czy wartości MousetrapsSet i MiceCaught są różne?”.
MousetrapsSet := 3
MiceCaught := 0
if (MousetrapsSet<>MiceCaught):
Print(“Potrzeba więcej sera!”)
Tym razem odpowiedź na pytanie brzmi tak, ponieważ MousetrapsSet ma wartość 3, a MiceCaught ma wartość 0, zatem wyrażenie zwróci powodzenie i blok kodu zostanie wykonany.
Wyrażenia decyzyjne
Wyrażenia decyzyjne, w których stosuje się operatory and, or i not, są wyrażeniami zawodnymi. W poniższym przykładzie MousetrapsForSale > 0 and Coins >= MousetrapCost jest wyrażeniem zawodnym, które zwróci powodzenie, ponieważ MousetrapsForSale wynosi 5 (czyli więcej niż 0), Coins wynosi 30, a MousetrapCost wynosi 20 (30 to więcej niż 20). Każde z wyrażeń z osobna zwróci powodzenie, zatem całe wyrażenie również zwróci powodzenie.
MousetrapsForSale := 5
MousetrapCost := 20
Coins := 30
if (MousetrapsForSale > 0 and Coins >= MousetrapCost):
Print(“Możesz kupić pułapki na myszy.”)
Wyrażenia zapytań
Wyrażenia zapytań również są wyrażeniami zawodnymi. Wykorzystują one operator ? do sprawdzania konkretnych wartości, na przykład do sprawdzania, czy wartość logic to true. W poniższym przykładzie MousetrapStoreOpen? jest wyrażeniem zawodnym, które zwróci niepowodzenie, ponieważ MousetrapStoreOpen ma wartość false.
var MousetrapStoreOpen : logic = false
if (MousetrapStoreOpen?):
Print(“Zapraszamy!”)
Konteksty niepowodzenia
W każdym z powyższych przykładów kodu wyrażenie if było kontekstem niepowodzenia dla wyrażeń zawodnych zawartych w (). Konteksty niepowodzenia stwarzają dla wyrażeń zawodnych bezpieczne otoczenie, w którym mogą okazywać się one zawodne, ponieważ określają, co ma się stać w przypadku niepowodzenia.
Wiesz już z poprzedniej lekcji, że w przypadku niepowodzenia wyrażenia należącego do bloku kodu if, kod z bloku kodu if nie zostanie uruchomiony.
Jednak wyrażenie if stwarza kontekst niepowodzenia, dlatego możesz umieścić w bloku jego kodu dowolną liczbę wyrażeń zawodnych. Jeśli dowolne z tych wyrażeń zwróci niepowodzenie, poprzedzające je w bloku kodu wyrażenia zostaną cofnięte.
Istnieje inny sposób zapisu wyrażeń if, bez użycia (). Sprawdza się on lepiej w przypadku pisania wielu wyrażeń. Oto przykład:
MousetrapsSet:int = 5
var MiceCaught:int = 0
var BreakTime:logic = false
if:
MousetrapsSet > 0
set BreakTime = true
MiceCaught > 0
if (BreakTime?):
Print("Zrób sobie przerwę!")
else:
Print("Zapoluj na myszy!")
W kontekście niepowodzenia nie wszystkie wyrażenia muszą być zawodne, ale wymagane jest, aby co najmniej jedno wyrażenie było. W powyższym przykładzie set BreakTime = true nie jest wyrażeniem zawodnym, ale pozostałe wyrażenia nimi są.
W powyższym kodzie każde wyrażenie zapisane z wcięciem pod if znajduje się wewnątrz kontekstu niepowodzenia. Wykonane zostaną wszystkie trzy wyrażenia.
- Wyrażenie
MousetrapsSet > 0zwróci powodzenie. - Wyrażenie
set BreakTime = truezostanie wykonane. Nie jest to wyrażenie zawodne, dlatego nie będzie ono sprawdzane pod kątem niepowodzenia. - Jednak wyrażenie
MiceCaught > 0zwróci niepowodzenie.
Ze względu na niepowodzenie, każde wyrażenie w bloku kodu if, łącznie z wyrażeniem set BreakTime = true, zostanie cofnięte. Rezultat będzie taki, jakby kod nigdy nie został uruchomiony. Jeśli uruchomisz ten kod, zobaczysz wyświetlony komunikat “Zapoluj na myszy!”.
W trakcie programowania zauważysz, że mnóstwo kodu działa tylko w przypadku pomyślnego wykonania innego kodu. To kolejny argument przemawiający za przydatnością kontekstów niepowodzenia. Pogrupowanie kodu zależnego do różnych kontekstów niepowodzenia pozwoli uniknąć często spotykanych błędów. Pamiętasz kod z lekcji 4 zastosowany do podjęcia decyzji o pójściu do kina? Teraz, gdy decyzja o wyjściu ze znajomymi już zapadła, musisz zadbać o ich bilety, napoje i przekąski!
var Drinks:int = 4
var Snacks:int = 4
var Tickets:int = 3
var FriendsAvailable:int = 4
if:
Drinks >= FriendsAvailable
set Drinks -= FriendsAvailable
Snacks >= FriendsAvailable
set Snacks -= FriendsAvailable
Tickets >= FriendsAvailable
set Tickets -= FriendsAvailable
Print("Pozostało napojów: { Drinks }")
Print("Pozostało przekąsek: { Snacks }")
Print("Pozostało biletów: { Tickets }")
Operator -= jest skrótem umożliwiającym połączenie odejmowania i przypisywania. W powyższym przykładzie wyrażenie set Tickets -= FriendsAvailable jest równoważne wyrażeniu set Tickets = Tickets - FriendsAvailable. Sprawdza się to również w przypadku dodawania (+=), mnożenia (*=) i dzielenia (/=).
Masz dostateczną liczbę napojów i przekąsek dla swoich znajomych, jednak biletów jest zbyt mało. Oznacza to, że ani ty, ani twoi znajomi nie możecie obejrzeć filmu. Możesz napisać kod, który pozwoli uporać się z tą sytuacją, ale prawdopodobnie nie chcesz rozdawać napojów i przekąsek.
Na szczęście uruchomienie wyrażenia Tickets >= FriendsAvailable spowoduje jego niepowodzenie, a cały kod z bloku if zostanie cofnięty. Oznacza to, że zmienne Drinks i Snacks z powrotem przyjmą wartość 4.
Podsumowanie
- W Verse niepowodzenie jest sposobem sterowania programem.
- Wyrażenia niepowodzenia mogą zwracać powodzenie lub niepowodzenie i muszą być zapisywane w kontekście niepowodzenia. To, co stanie się po zwróceniu powodzenia lub niepowodzenia, zależy od tego, jak kod zostanie zapisany.
- Konteksty niepowodzenia stwarzają dla wyrażeń zawodnych bezpieczne otoczenie, w którym mogą okazywać się one zawodne. Każde niepowodzenie w kontekście niepowodzenia powoduje cofnięcie całego kodu w tym kontekście tak, jakby nigdy nie został on uruchomiony.