Protected execution is q’s model of exception handling. If you are familiar with exception models (such as try, catch, and throw) from another language, you will notice a resemblance.

In any exception handling model, there is a block of code to attempt to execute and one or more blocks of code to invoke should the attempted block fail. Moreover, the error handling blocks have a proscribed form. Lastly, there is a mechanism to raise an exception.

Let’s look at a simple example in q and break it down:

LaidBackLoad: {[file]
@[{system "l ", x; 1b}; / code to attempt
file;                 / argument
{[err] 0N! err; 0b}]} / error handler

In q, there is only one error handling block, and both the try block and the error handling block must be functions. In addition, the error handler takes a single parameter, which – if the error handler is called – will be a string.

In our example, the function to try takes only a single parameter, and that’s why the protected execution expression starts with an @. If your try function takes more than one parameter, use . instead:

LaidBackEqual: {
.[{x = y};              / code to attempt
(x; y);               / arguments
{[err] 0N! err; 0b}]} / error handler

You signal an error (which may be a symbol or a string) using the ‘ (signal) operator:

CantBeNegative: {if [x < 0; ‘ “Must be >= 0”]; x}

This is exactly the same mechanism that q uses to let us know when we have done something wrong:

q)(1 2 3) = 1 2

There is one last detail to note when reviewing the above examples. Protected execution expressions are expressions, and they have a value. If the try function does not signal, then the expression’s value is the try function’s return value. Otherwise, the protected execution expression’s value is the value returned by the error handler.