Выражение defer задерживает выполнение кода до момента выхода за пределы текущей области видимости. Вы можете использовать выражение defer для выполнения задач очистки, таких как сброс переменных. Даже при использовании выражений, подразумевающих досрочный выхода за пределы области видимости (например, return или break), выражения в блоке defer будут выполняться до тех пор, пока defer встречается перед выходом.
В представленном ниже коде демонстрируется, как defer применяется для сброса переменной на 0, хотя эта переменная всё ещё используется в качестве значения return. В этой функции возвращается значение RoundScore, а выражения из блока defer выполняются сразу после этого.
Это означает, что вам не нужно создавать временную переменную для сохранения значения RoundScore до того, как оно будет сброшено на 0.
OnRoundEnd<public>() : void =
var ScoreThisRound : int = AddRoundScoreToTotalScore()
Print("Заработано очков за этот раунд: {ScoreThisRound}")
<# Прибавить RoundScore к TotalScore и сбросить RoundScore на 0.
Возвращает прибавляемое значение RoundScore. #>
AddRoundScoreToTotalScore<public>() : int =
defer:
set RoundScore = 0
UpdateUI()
set TotalScore += RoundScore
return RoundScore
Использование выражения defer
Вы можете использовать выражение defer в любых блоках кода с последовательным выполнением, таких как block, loop, for, if, branch или даже в другом блоке defer.
Выражения в блоке defer должны быть с немедленной синхронизацией (а не асинхронными) — с одним исключением. Асинхронные выражения по-прежнему можно использовать в блоке defer, если они выполняются немедленно с помощью:
- spawn:
branch(еслиdeferрасполагается в асинхронном блоке, например, в сопрограмме).
defer не имеет результата и не может использоваться в качестве аргумента или присваиваемого значения.
| defer | defer перед выходом |
|---|---|
|
|
Нажмите на изображение, чтобы увеличить его. |
Нажмите на изображение, чтобы увеличить его. |
Выражение defer будет выполнено, только если произойдёт досрочный выход за пределы блока.
| defer с преждевременным возвратом | defer с отменённым асинхронным выражением |
|---|---|
|
|
Нажмите на изображение, чтобы увеличить его. |
Нажмите на изображение, чтобы увеличить его. |
Несколько выражений defer в одной области видимости накапливаются. Выполняться они будут в порядке, обратном тому, в котором они встречаются — то есть в порядке «первый вошёл, последний вышел» (first-in-last-out, или FILO). Поскольку последний блок defer в определённой области видимости выполняется первым, выражения внутри этого последнего блока defer могут ссылаться на контекст (например, переменные), который будет уже удалён другими выражениями defer, встречающимися раньше и исполняемыми позже.
В Verse не используется детерминированное уничтожение, но выражение defer позволяет создать поведение, подобное принципу Resource Acquisition Is Initialization (Получение ресурса означает его инициализацию, RAII), для гарантированного удаления объектов.
| Несколько выражений defer в одном блоке | Несколько выражений defer в разных блоках |
|---|---|
|
|
Нажмите на изображение, чтобы увеличить его. |
Нажмите на изображение, чтобы увеличить его. |
Преждевременный выход в блоке defer допускается до тех пор, пока выход не передаёт управление за пределы области видимости defer. Например, использование цикла с break разрешено внутри defer, но выражение breakдолжно продолжать выполнение кода внутри блока defer. Оно не может ссылаться на loop за пределами блока defer.
Любые переменные, которые встречаются во внешней области видимости вложенной структуры выражения defer, могут использоваться внутри этого выражения defer.
Помните, что при выходе за пределы области видимости выражение defer выполняется последним. Это означает, что оно использует любое состояние программы (включая значения переменных) в момент выхода, а не в момент, когда встречается defer. Код ниже выведет на дисплей результат 10, потому что defer запускается непосредственно после MyScore, для которой задано значение 10.
var MyScore = 5
defer:
Print(MyScore)
set MyScore = 10
Если использовать выражение deferв качестве последнего выражения в области видимости, то это равносильно тому, что оно не используется совсем. Например, эти два набора выражений будут выполняться в одном и том же порядке, поэтому defer не нужно:
| Без defer | С defer |
|---|---|
|
|