The defer
expression delays the execution of code until the current scope exits. You can use the defer
expression to handle cleanup tasks like resetting variables. Even when there is an early exit (such as return
or break) from the current scope, the expressions in a defer
block will run as long as defer
is encountered before the exit.
The following code shows how to use defer
to reset a variable to zero while still using that same variable as a return value. In this function, RoundScore
is returned and the expressions in the defer
block run immediately after.
This means you do not need to create a temporary variable to save the value of RoundScore
before it gets reset to zero.
OnRoundEnd<public>() : void =
var ScoreThisRound : int = AddRoundScoreToTotalScore()
Print("Points scored this round: {ScoreThisRound}")
<# Adds RoundScore to TotalScore and resets RoundScore to 0.
Returns the RoundScore added. #>
AddRoundScoreToTotalScore<public>() : int =
defer:
set RoundScore = 0
UpdateUI()
set TotalScore += RoundScore
return RoundScore
Defer Expression Use
You can use a defer
expression within any sequential code block such as a block, loop, for, if, branch, or even another defer
.
Expressions within a defer
block must be immediate (and not async) — with one exception. Async expressions can still be used within a defer
if they are made immediate by using:
- spawn
branch
(if thedefer
is within an async block such as in a coroutine)
A defer
has no result, and cannot be used as an argument or an assignment value.
defer | defer before an exit |
---|---|
|
|
A defer
expression will only execute if it is encountered before an early exit occurs.
defer with early return | defer with a canceled async expression |
---|---|
|
|
Multiple defer
expressions appearing in the same scope accumulate. The order they are executed is the reverse order they are encountered — first-in-last-out (FILO) order. Since the last encountered defer
in a given scope is executed first, expressions inside that last encountered defer
can refer to context (such as variables) that will be cleaned up by other defer
expressions that were encountered earlier and executed later.
Verse does not have deterministic destruction, but defer
allows behavior similar to RAII to ensure cleanup.
Multiple defer expressions in a code block | Multiple defer expressions in different code blocks |
---|---|
|
|
Exiting early is allowed within a defer
block as long as the exit does not transfer control outside the scope of the defer
. For example, using a loop with break
is allowed within a defer
, but that break
must keep the code execution within the defer
block. It cannot refer to a loop
outside of the defer
block.
Any variables that have been encountered in the outer nesting scope of a defer
can be used within that defer
expression.
Remember that defer
runs last at the time of scope exit. This means that it uses whatever the state of the program is (including variable values) at that time, not at the time when the defer
is encountered. The code below will print 10
because defer
runs immediately after MyScore
is set to 10
.
var MyScore = 5
defer:
Print(MyScore)
set MyScore = 10
Using a defer
expression as the last expression within a scope is the same as not using it at all. For example, these two sets of expressions will run in exactly the same order, so defer
is not needed:
Without defer | With defer |
---|---|
|
|