defer
式 は、現在の スコープ を終了するまでコードの実行を遅らせることができます。defer
式を使用すると、変数 のリセットなどのクリーンアップ タスクを処理することができます。現在のスコープを早い段階で終了する場合 (return
または break など) でも、defer
ブロック内の式は、終了する前に defer
が検出される限り実行されます。
次のコードは、defer
を使用して変数をゼロにリセットしながら、その変数を return 値として使用する方法を示しています。この 関数 では、RoundScore
が返され、その直後に defer
ブロック内の式が実行されます。
つまり、ゼロにリセットされる前に、RoundScore
の値を保存するための一時的な変数を作成する必要はありません。
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 式の使用方法
defer
式は、block、loop、for、if、branch など、任意のシーケンシャル コード ブロック 内、または他の defer
でも使用することができます。
defer
ブロック内の式は、(非同期 式ではなく) 即時 式である必要があります。ただし、例外が 1 つあります。非同期式でも、以下を使用してその式を即時式にした場合は、defer
内で使用できます。
- spawn
branch
(defer
がコルーチン内にあるなど非同期ブロック内にある場合)
defer
は結果がないため、引数や代入値として使用することはできません。
defer | 終了する前に defer |
---|---|
|
|
画像をクリックすると拡大表示されます。 |
画像をクリックすると拡大表示されます。 |
defer
式は、早期に終了する前に検出された場合のみ実行されます。
早期に戻り値が得られる場合の defer | 非同期式がキャンセルされた場合の defer |
---|---|
|
|
画像をクリックすると拡大表示されます。 |
画像をクリックすると拡大表示されます。 |
同じスコープに出現する複数の defer
式は累積されます。それらが実行される順序は、検出された逆の順序、つまり先入れ後出し (FILO) 順です。特定のスコープ内で最後に検出された defer
が最初に実行されるため、その最後に検出された defer
の内部にある式は、以前に検出され、後に実行された他の defer
式によってクリーンアップされるコンテキスト (変数など) を参照できます。
Verse には 決定論的デストラクション はありませんが、defer
を使用すると RAII と同様の動作でクリーンアップを確実に行うことができます。
コード ブロック内の複数の defer 式 | 異なるコード ブロック内の複数の defer 式 |
---|---|
|
|
画像をクリックすると拡大表示されます。 |
画像をクリックすると拡大表示されます。 |
defer
ブロック内での早期終了は、その終了が defer
のスコープ外に制御を転送しない限り許可されます。たとえば、ループを break
と併用することは defer
内では可能であるものの、break
でコードの実行が defer
ブロック内で保持されている必要があります。defer
ブロック外から loop
を参照することはできません。
defer
の外側で ネスティング スコープで検出されたすべての変数は、その defer
式内で使用することができます。
なお、defer
は、スコープの終了時の最後に実行されます。つまり、defer
の検出時ではなく、その時点のプログラムの状態 (変数の値を含む) を問わず、defer が使用されます。以下のコードでは、10
が出力されます。これは、defer
が、MyScore
が 10
に設定された直後に実行されるためです。
var MyScore = 5
defer:
Print(MyScore)
set MyScore = 10
defer
式をスコープ内の最後の式として使用することは、その式をまったく使用しないことと同じになります。たとえば、これら 2 組の式はまったく同じ順序で実行されるため、defer
は必要ありません。
defer なし | defer あり |
---|---|
|
|