スコープ
前の章で見たように、常に実行しなければならない式はfinallyブロックで記述し、エラー条件が発生した場合に実行しなければならない式はcatchブロックで記述する。
これらのブロックの使用について、以下の点が指摘できる。
catchfinallyは、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文を逆の順序で実行すると、前の式の副作用を一貫した順序で元に戻すことができる。