スコープ
前の章で見たように、常に実行しなければならない式はfinally
ブロックで記述し、エラー条件が発生した場合に実行しなければならない式はcatch
ブロックで記述する。
これらのブロックの使用について、以下の点が指摘できる。
catch
finally
は、try
ブロックなしでは使用できない。- これらのブロックが必要とする変数のいくつかは、これらのブロック内ではアクセスできない場合がある。
この関数は、まず参照パラメータを変更し、例外がスローされたときにこの変更を元に戻す。残念ながら、
addend
は、それが定義されているtry
ブロック内でのみアクセス可能だ。(注釈:これは、オブジェクトのライフタイムだけでなく、名前スコープにも関係している。これについては、後の章で説明する。) - 関連性がない可能性のある式をすべて、一番下の単一の
finally
ブロックに記述することで、それらの式を、それらが関連している実際のコードから分離することができる。
scope
文は、catch
およびfinally
スコープと似た機能を持っているが、多くの点で優れている。finally
と同様に、3つの異なるscope
文は、スコープを離れるときに式を実行するものだ。
scope(exit)
: スコープを離れるときに、成功したか、例外が発生したかに関係なく、式は常に実行される。scope(success)
: 式は、スコープを正常に終了した場合にのみ実行されるscope(failure)
: 例外によってスコープが終了した場合にのみ、式が実行される。: 例外によってスコープが正常に終了した場合にのみ、式が実行される。
これらの文は例外と密接に関連しているが、try-catch
ブロックを使用せずに使用することができる。
例として、上記の関数をscope(failure)
文を使って記述しよう。
上記のscope(failure)
文は、例外によって関数のスコープが終了した場合に、r -= addend
式が確実に実行されるようにする。scope(failure)
の利点は、別の式を元に戻す式がその式に近い場所に記述できることだ。
scope
文はブロックとして指定することもできる。
3つの文すべてをテストする別の関数を以下に示す。
例外がスローされなかった場合、関数の出力にはscope(exit)
およびscope(success)
式のみが含まれる。
when exiting 2
if successful 1
if successful 2
when exiting 1
例外がスローされた場合、出力にはscope(exit)
およびscope(failure)
式が含まれる。
if thrown 2
when exiting 2
if thrown 1
when exiting 1
object.Exception@...: エラーメッセージ
出力からわかるように、scope
文のブロックは逆の順序で実行される。これは、後のコードが前の変数に依存している可能性があるためだ。scope
文を逆の順序で実行すると、前の式の副作用を一貫した順序で元に戻すことができる。