Publication date: 05/24/2021

Throw and Catch Exceptions

A script can stop itself by executing the Throw() function. If you want to escape from part of a script when it is in an error condition, you can enclose it in a Try() expression.

If you include a character-valued expression as a Throw() argument, one of the following occurs:

Throwing stores the string in a global variable named exception_msg. This is illustrated in the first example below.

Throwing stores the string in a local variable named exception_msg if you define exception_msg in the Here namespace using Names Default to Here(1).

Try() takes two expression arguments. It starts by evaluating the first expression, and if or when the first expression throws an exception by evaluating Throw, it does the following:

1. Immediately stops evaluating that first expression.

2. Returns nothing

3. Evaluates the second expression.

Examples

You can use Try() and Throw() to catch an exception that JMP itself throws.

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

exception_msg = "Hello.";

The following example prints a message to the log when the Try() expression cannot be executed:

Try(
	dt = Open( "Mydata.jmp" ); // a file that cannot be opened
	Summarize( a = by( age ), c = count, meanHt = Mean( Height ) );
	Show( a, c, meanHt );
,
	Print( "This script does not work without the data set." );
	Throw();
);

If the Throw() string begins with “!” and is inside a Try() expression, throwing creates an error message about where the exception was caught.

Try(
	Throw( "!This message has an exclamation point." );
,
	Write( "\!Nexception_msg: ", exception_msg );
	Print( "Hello from the catch block (WITH exclamation)." );
);
Print( "This AFTER message will NOT print due to error." );

When writing the Try() error handler code, consider wrapping the exception variable exception_msg in a Char() function. If your script calls Concat() without wrapping it in a Char() call, you might get an error depending on what was actually returned in this variable. Though some commands return a string in exception_msg, other commands (such as Open()) return a list or another data structure. This would cause an error in the error handler if it were passed directly as an argument to Concat().

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

// use Write to print "no error"if exception_msg is empty

		Write( "\!Nexception_msg (0): no error" ),

// use Print to print the exception message

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

/* or first make sure that exception message is a string

and then use Concat to build the message that is passed to Print(). */

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

exception_msg (1): "

{"Cannot open table"(1, 2, "Open", Open /*###*/("no file"))}

"

exception_msg (2): {\!"Cannot open table\!"(1, 2, \!"Open\!", Open /*###*/(\!"no file\!"))}"

You can also use Try() and Throw() to escape from deep inside For loops.

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

// a[2, 3] = 2; // uncomment this line to see the "Missing b" outcome

 
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";

You do not have to use Try() to make use of Throw(). In this example, Throw() is not caught by Try() but still stops a script that cannot proceed:

dt = New Table(); // to get an empty data table
If( N Row( dt ) == 0,
	Throw( "!Empty Data Table" )
);
Want more information? Have questions? Get answers in the JMP User Community (community.jmp.com).