公開日: 11/25/2021

例外のスローとキャッチ

Throw()関数を実行することにより、そのスクリプト自体を停止できます。スクリプトがエラー状態に入ってしまったときにその部分から抜け出すためには、Try()関数でそのスクリプトを囲んでおきます。

Throw()引数を指定した場合、次のいずれかの処理が行われます。

exception_msgという名前のグローバル変数にその文字列が格納されます。これについては、次の最初の例で示します。

Names Default to Here(1)を使ってexception_msgがHere名前空間内で定義された場合は、exception_msgという名前のローカル変数にその文字列が格納されます。

Try()関数は、2つの式を引数としてとります。Try関数はまず1つ目の式を評価します。1つ目の式がThrow()の評価によって例外を戻したときは、次を実行します。

1. 評価をそこですぐに停止する。

2. 何も戻さない。

3. 2番目の式を評価する。

Try()Throw()を使って、JMPそのものが出す例外を受け取ってスクリプトを停止させることができます。

Try( Throw( "Hello." ), Show( exception_msg ) );

exception_msg = "Hello.";

次の例では、Try()式を実行できないときにメッセージをログに出力します。

Try(
	dt = Open( "Mydata.jmp" ); // 開くことができないファイル
	Summarize( a = by( 年齢 ), c = count, meanHt = Mean( :"身長(インチ)"n ) );
	Show( a, c, meanHt );
,
	Print( "このスクリプトは、データセットがないと動作しません。" );
	Throw();
);

Throw()文字列が「!」で始まり、Try()式の中にある場合、Throwは例外が見つかった場所に関するエラーメッセージを作成します。

Try(
	Throw( "!メッセージに感嘆符を含めます" );
,
	Write( "\!Nexception_msg: ", exception_msg );
	Print( "例外をキャッチしたブロックのメッセージ(感嘆符含む)" );
);
Print( "このメッセージはTryの後にあるためエラーがあると出力されません" );

Try()エラーハンドラーのコードを書く際は、例外の変数exception_msgChar()関数の中に指定するようにしてください。 Char()で囲まれていない Concat()をスクリプトが呼び出すと、この変数で戻された値によってはエラーになることがあります。exception_msgで文字列を戻すコマンドもありますが、他のコマンド(Open()など)はリストまたは別のデータ構造を戻します。これが引数としてConcat()に直接渡されると、エラーハンドラー内でエラーが生じます。

Try(
	Open( "no file" ),
	If( Is Empty( exception_msg ),

// Writeを使い、exception_msgが空白の場合に"エラーなし"と出力されるようにする

		Write( "\!Nexception_msg (0): エラーなし" ),

// Printを使い、例外メッセージが出力されるようにする

		Print( "\!Nexception_msg (1): ", exception_msg );

/* または、例外メッセージが文字列になるようにし、

Concatを使ってPrint()に渡されるメッセージを作成する*/

		Print( "\!Nexception_msg (2): " || Char( exception_msg ) );
	)
);

exception_msg (1): "

{"テーブルを開けません"(1, 2, "Open", Open /*###*/("no file"))}

"

exception_msg (2): {\!"テーブルを開けません\!"(1, 2, \!"Open\!", Open /*###*/(\!"no file\!"))}"

また、Try()Throw()を使うと、Forループの入れ子の中から抜け出ることができます。

a = [1 2 3, 4 5 ., 7 8 9];
b = a;
nr = N Row( a );
nc = N Col( a );

// a[2, 3 ] = 2; // "Missing b"という結果を表示させる場合は、この行のコメントを外す

 
Try(
	sum = 0;
	For( i = 1, i <= nr, i++,
		For( j = 1, j <= nc, j++,
			za = a[i, j];
			If( Is Missing( za ),
				Throw( "Missing a" )
			);
			zb = b[j, i];
			If( Is Missing( zb ),
				Throw( "Missing b" )
			);
			sum += za * zb;
		)
	);
,
	Show( i, j, exception_msg );
	Throw();
);

i = 2;

j = 3;

exception_msg = "Missing a";

Throw()を使うために、必ずしもTry()を使う必要はありません。次の例では、Try()によってThrow()を受け取るのではなく、自らスクリプトを停止させます。

dt = New Table(); // 空のデータテーブルを作成
If( N Row( dt ) == 0,
	Throw( "!空のデータテーブル" )
);
より詳細な情報が必要な場合や、質問があるときは、JMPユーザーコミュニティで答えを見つけましょう (community.jmp.com).