Za pomocą wyrażeń case można sterować przepływem programu z poziomu listy wyboru. Polecenie case w Verse to sposób na testowanie jednej wartości względem wielu możliwych wartości (tak jak przy użyciu =) i uruchamianie kodu na podstawie tego, która z nich pasuje.
Wyrażenia case można znaleźć we wszystkich rodzajach zastosowań, na przykład w grach, w których występuje postać niezależna (NPC).
Załóżmy na przykład, że używasz urządzenia generatora strażników z włączoną funkcją patrolowania. Gdy strażnik pojawia się w grze, ma kilka możliwych stanów aktywnych, takich jak bezczynność, patrol, alarm, atak i zbieranie surowców. Przykładowy diagram przejścia między stanami może wyglądać następująco:
Te przejścia między stanami możesz obserwować w grze.
Na tym filmie strażnik ma włączoną opcję patrolowania jako zachowanie domyślne.
Na filmie strażnik przechodzi od patrolowania bazy naukowej do zbierania niektórych zasobów. Następnie strażnik zauważa gracza, co powoduje przejście strażnika w stan alarmu (oznaczony zawieszonym znakiem zapytania) przed przejściem w stan ataku (oznaczony zawieszonym wykrzyknikiem).
W zależności od stanu, w jakim jest strażnik, będzie on wykazywał pewne zachowania, które są zwykle zakodowane jako funkcje wywoływane, gdy program postanowi wejść w określony stan.
Jako kod, to zaawansowane przejście między stanami strażnika może wyglądać następująco:
case(GuardStateVariable):
idle_state =>
RunIdleAnimation()
SearchPlayerCharacter()
harvest_state =>
GatherResources()
alert_state=>
RunAlertAnimation()
PlayAlertSound()
DisplayAlertUIElement()
To wyrażenie case przekazuje etykietę, która informuje program, jakie funkcje należy uruchomić, gdy strażnik przejdzie w określony stan.
W tym wyrażeniu stan strażnika patrol_state jest przypadkiem domyślnym, ponieważ strażnik z włączonym stanem patrolu powinien uruchomić swoje domyślne zachowanie dla tego stanu.
Składniowo wygląda to tak samo jak:
expression0
case (test-arg-block):
label1 =>
expression1
label2 =>
expression2
_ =>
expression3 for the default case
expression4Każdy wzór w bloku case, taki jak label1 i label2, musi mieć postać constant => block, gdzie stała może być liczbą całkowitą, wartością logiczną, ciągiem tekstowym, znakiem lub typem wyliczeniowym. Zatem polecenia case działają tylko z typami int, logic, string, char i enum.
Struktura
Pod względem strukturalnym wyrażenie case w Verse uruchamia kod na podstawie danych wejściowych bloku argumentów testu GuardStateVariable, a pod względem funkcjonalnym działa tak samo jak seria wyrażeń if.
W tym przykładzie program Verse uruchamia wyrażenie expression3, jeśli GuardStateVariable zmienia się na alert_state. Jeśli program przechodzi do stanu patrol_state, Verse strukturalnie przechodzi do przypadku domyślnego i uruchamia wyrażenie expression5.
Używanie wyrażenia case z innymi przepływami sterowania
Bloki w poleceniu case mogą być przerywane i kontynuowane, jeśli polecenie case znajduje się wewnątrz loop. Bloki poleceń case mogą również wracać z funkcji, w której się znajdują.
Na przykład:
loop:
case (x):
42 => break
_ => {}Ta absurdalna pętla zakończy się natychmiast, jeśli x = 42, lub zapętli się w nieskończoność.
Inny przykład:
Foo(x : int) : int =
case (x):
100 => return 200
_ => return 100Ten przykład jest odpowiednikiem tego:
Foo(x : int) : int =
case (x):
100 => 200
_ => 100Dzieje się tak dlatego, że polecenie case jest ostatnim wyrażeniem funkcji.
Domyślny przypadek
Polecenia case, które nie mają wyrażenia case _=> (przypadek domyślny) zakończą się niepowodzeniem, jeśli żaden z przypadków nie będzie pasował. Takich poleceń case można używać w kontekstach niepowodzenia (takich jak funkcje z efektem decides).
Polecenia case, które pasują do wszystkich przypadków wyliczenia, nie zakończą się niepowodzeniem, nawet jeśli nie mają wyrażenia case _=>.