Неоднозначность — это способ контроля исполнения в Verse.
В отличие от других языков программирования, которые используют булевы значения true и false для изменения потока выполнения программы, в Verse применяются выражения, которые могут завершиться либо успешно, либо с ошибкой. Такие выражения называются выражениями с неоднозначным результатом и могут выполняться только в контексте, допускающем неоднозначность.
Использование неоднозначности для контроля исполнения означает, что работу не нужно дублировать и можно избежать мелких ошибок.
Например, в других языках перед обращением к элементу массива с таким индексом необходимо проверить, что индекс массива является действительным, что ведёт к большому числу ошибок.
В Verse проверка и обращение объединены, чтобы избежать этого.
Например:
if (Element := MyArray[Index]):
Log(Element)
Выражение с неоднозначным результатом
Выражение с неоднозначным результатом — это выражение, которое может либо выполниться удачно и вернуть значение, либо завершиться с ошибкой и не вернуть никакого значения. Примеры выражений с неоднозначным результатом включают индексирование массива, поскольку при неправильном индексе произойдёт ошибка, и использование операторов, например сравнение двух значений.
Код, который вы пишете, не является «кодом с неоднозначным результатом» по умолчанию. Например, чтобы написать функцию, допускающую неоднозначность, вы должны добавить в её определение спецификатор эффекта <decides>. В данный момент также необходимо добавить <transacts>, если используется <decides>.
Полный список выражений с неоднозначным результатом, см. в списке Выражения в Verse.
Контекст, допускающий неоднозначность
Контекст, допускающий неоднозначность — это контекст, в котором допустимо выполнение выражений с неоднозначным результатом. Данный контекст определяет, что происходит, если выражение завершится с ошибкой. Любая ошибка в данном контексте приводит к ошибке всего контекста.
Контекст, допускающий неоднозначность, позволяет выражениям внутри него выступать в качестве выражений с неоднозначным результатом — это могут быть аргументы функций или выражения внутри выражения block.
Полезной возможностью контекстов, допускающих ошибки, в Verse является то, что они допускают спекулятивное выполнение, которое подразумевает, что вы можете опробовать те или иные действия без фиксации изменений. Если выражение завершается успешно, то изменения фиксируются; к примеру, это может быть изменение значения переменной. Если же выражение выдаёт ошибку, последствия выполнения выражения откатываются, как будто выражение никогда не выполнялось.
Таким образом, вы можете выполнить ряд действий, накопив все сопутствующие изменения, которые всегда можно отменить, если одно из действий будет завершено с ошибкой.
Для этого все функции, вызываемые в данном контексте, должны иметь спецификатор эффекта <transacts>, и если его нет, компилятор должен сообщить об этом.
Определяемые пользователем функции по умолчанию на содержат спецификатора transacts. Он должен быть добавлен в определение функции. Некоторые нативные функции также не <transacts> и не могут быть вызваны в контекстах, допускающих неоднозначность.
Примером нативной функции без transacts может быть audio_component с методом BeginSound(). Если звук запущен, то это можно заметить, даже если он прекратился.
Ниже перечислены разновидности контекстов в Verse, допускающих ошибки:
-
Условие в выражениях
if.if (test-arg-block) { … } -
Выражения итерации и фильтрации в выражениях
for. Обратите внимание: особенность выраженияforзаключается в том, что оно создаёт контекст, допускающий неоднозначность, для каждой итерации. Если итерации выполняются как вложенные, контекст, допускающий неоднозначность, тоже будет вложенным. Когда выражение завершается с ошибкой, внутренний контекст, допускающий неоднозначность, прерывается, а внешняя итерация, если таковая имеется, продолжается со следующей итерации.for (Item : Collection, test-arg-block) { … } -
Тело функции, имеющей спецификатор эффекта
<decides>.IsEqual()<decides><transacts> : void = { … } -
Операнд оператора
not.not expression -
Левый операнд оператора
or.expression1 or expression2 -
Инициализация переменной типа
option.option{expression}