С помощью выражений case можно осуществлять контроль исполнения программы с выбором из списка вариантов. Оператор case в Verse позволяет сравнить одно значение с несколькими возможными значениями (подобно оператору =) и затем выполнить код с учётом совпадений.
Выражения case используются в самых разных приложениях, например в играх, где есть неигровой персонаж (NPC).
Представьте, что вы используете устройство Генератор охранников для создания охранника с включённой опцией патрулирования. После появления в игре у него есть несколько возможных активных состояний, включая Бездействие, Патрулирование, Тревога, Атака и Добыча ресурсов. В этом случае высокоуровневая диаграмма переходов между состояниями может выглядеть так:
Эти переходы между состояниями можно наблюдать внутри игры.
В этом видео у охранника в качестве поведения по умолчанию включена опция патрулирования.
На видео охранник переходит от патрулирования научной базы к добыче ресурсов. Затем охранник замечает игрока, из-за чего он переходит в состояние тревоги (обозначается парящим вопросительным знаком), а затем в состояние атаки (обозначается парящим восклицательным знаком).
В зависимости от состояния, в котором находится охранник, он будет демонстрировать определённое поведение, и это поведение обычно кодируется как функции, которые вызываются, когда программа переходит в определённое состояние.
Этот высокоуровневый переход между состояниями охранника можно закодировать следующим образом:
case(GuardStateVariable):
idle_state =>
RunIdleAnimation()
SearchPlayerCharacter()
harvest_state =>
GatherResources()
alert_state=>
RunAlertAnimation()
PlayAlertSound()
DisplayAlertUIElement()
Это выражение case передаёт метку, которая указывает программе, какие функции следует выполнить при переходе охранника в определённое состояние.
В данном выражении patrol_state охранника — это вариант по умолчанию, потому что охранник с включённым патрулированием должен принимать поведение патрулирования по умолчанию.
Синтаксически это эквивалентно следующему коду:
expression0
case (test-arg-block):
label1 =>
expression1
label2 =>
expression2
_ =>
expression3 for the default case
expression4Для каждого шаблона в блоке case, такого как label1 и label2, следует использовать форму константа => блок, где константа может принимать тип integer, logic, string, char или enum. Поэтому операторы case работают только с данными типа int, logic, string, char и enum.
Структура
Структурно выражение case в языке Verse запускает код на основе входных данных блока проверки аргумента GuardStateVariable, а функционально работает так же, как серия выражений if.
В этом примере программа Verse запускает expression3, если GuardStateVariable имеет значение alert_state. Если программа переходит в patrol_state, Verse структурно переходит к случаю по умолчанию и выполняет expression5.
Использование case с другими средствами контроля исполнения
Блоки в операторе case могут прерываться и продолжаться, если оператор case находится внутри цикла loop. Блоки операторов case также могут осуществлять возврат из функции, в которой они находятся.
Пример:
loop:
case (x):
42 => break
_ => {}Этот абсурдный цикл либо завершится мгновенно, если x = 42, либо будет выполняться бесконечно.
Другой пример:
Foo(x : int) : int =
case (x):
100 => return 200
_ => return 100Этот пример эквивалентен следующему:
Foo(x : int) : int =
case (x):
100 => 200
_ => 100Этот пример эквивалентен первому, потому что оператор case является последним выражением функции.
Case по умолчанию
Операторы case, в которых нет варианта _=> (случай по умолчанию), будут выдавать ошибку, если ни один из вариантов не совпадает. Такие операторы case можно использовать в контекстах, допускающих неоднозначность, (например, в функциях с эффектом decides).
Операторы case, в которых есть совпадение для всех вариантов перечисления, не выдают ошибку, даже если они не имеют варианта _=>.