>>  <<  Usr  Pri  JfC  LJ  Phr  Dic  Rel  Voc  !:  Help  Learning J

# Chapter 29: Error Handling

The plan for this chapter is to look at some of the J facilities for finding and dealing with programming errors. It is beyond the scope of this chapter to consider debugging strategies, but (in my view) the use of assertions is much to be recommended. We look at:
• Assertions
• Continuing after failure
• Suspended execution
• Programmed error-handling

## 29.1 Assertions

A program can be made self-checking to some degree. Here is an example of a verb which computes the price of an area of carpet, given a list of three numbers: price per unit area, length and width.
```   carpet =: 3 : 0
*/ y
)

carpet 2 3 4
24
```
Assume for the sake of example that the computation */y is large and problematic, and we want some assurance that the result is correct. We can at least check that the result is reasonable; we expect the price of a carpet to lie between, say, \$10 and \$10,000.

We can redefine carpet, asserting that the result p must be between 10 and 10000:

```   carpet =: 3 : 0
p =. */y
assert. p >: 10
assert. p <: 10000
p
)
```
If an assertion is evaluated as true (or "all true") there is no other effect, and the computation proceeds.
```   carpet 2 3 4
24
```
If an assertion is evaluated as false, the computation is terminated and an indication given:
```   carpet 0 3 4
|assertion failure: carpet
|   p>:10
```
Assertions can only be made inside explicit definitions, because assert. is a "control word", that is, an element of syntax, not a function.

It always a matter for judgement as to where an assertion can usefully be placed, and what can usefully be asserted. Assertions are best kept as simple as possible, since it is highly undesirable to make an error in an assertion itself.

It is often useful to make assertions which check the correctness of arguments of functions. For example, we could assert that, for carpet the argument y must be a list of 3 strictly positive numbers.

The order of assertions may be important. For example, we should check that we have numbers before checking the values of those numbers. The type of a noun is given by 3!:0; here we want integers (type=4) or reals (type=8).

```   carpet =: 3 : 0

assert. (3!:0 y) e. 4 8   NB. numeric
assert. 1 = # \$ y         NB. a list (rank = 1)
assert. 3 = # y           NB. of 3  items
assert. *. / y > 0        NB. all positive

p =. */y

assert. p >: 10
assert. p <: 10000

p
)

carpet 2 3 4
24

carpet 'hello'
|assertion failure: carpet
|   (3!:0 y)e.4 8

```

### 29.1.1 Enabling and Disabling Assertions

When we are confident of correctness, we can consider removing assertions from a program, particularly if performance is an issue. Another possibility is to leave the assertions in place, but to disable them. In this case, asserted expressions are not evaluated, and assertions always succeed. There is a built-in function 9!:35 to enable or disable assertions. For example:
```   (9!:35) 0      NB. disable assertions
carpet 0 3 4   NB. an error
0

(9!:35) 1      NB. enable assertions
carpet 0 3 4   NB. an error
|assertion failure: carpet
|   *./y>0

```
The built-in function 9!:34 tests whether assertions are enabled. Currently they are:
```   9!:34 ''   NB. check that assertions are enabled
1
```

## 29.2 Continuing after Failure

There are several ways to continue after a failure.

### 29.2.1 Nonstop Script

In testing a program, it may be useful to write a script for a series of tests. Here is an example of a test-script.
```   (0 : 0) (1!:2) <'test.ijs'   NB. create test-script

NB. test 1
carpet 10  0 30

NB. test 2
carpet 10 20 30
)
```
A test may give the wrong result, or it may fail altogether, that is, it may be terminated by the system. We can force the script to continue even though a test fails, by executing the script with the built-in verb 0!:10 or 0!:11
```   0!:11 <'test.ijs'            NB. execute test-script

NB. test 1
carpet 10  0 30
|assertion failure: carpet
|   *./y>0

NB. test 2
carpet 10 20 30
6000

```

### 29.2.2 Try and Catch Control Structure

Here is an example of a verb which translates English words to French using word-lists.
```   English =: 'one'; 'two';  'three'
French  =: 'un';  'deux'; 'trois'

ef =:  3 : '> (English i. < y) { French'
```
A word not in the list will produce an error.

 ef 'two' ef 'seven' deux error

This error can be handled with the try. catch. end. control structure. (Chapter 12 introduces control structures)

```   EF =: 3 : 'try. ef y catch. ''don''''t know'' end.'

```

 EF 'two' EF 'seven' deux don't know

The scheme is that

```             try. B1 catch. B2 end.
```
means: execute block B1. If and only if B1 fails, execute block B2.

A tacit version of the last example can be written with the "Adverse" conjunction :: (colon colon).
```   TEF =: ef :: ('don''t know' " _)

```

 TEF 'two' TEF 'seven' deux don't know

Notice that the left and right arguments of :: are both verbs. The scheme is:

```           (f :: g) y
```
means: evaluate f y. If and only if f y fails, evaluate g y

## 29.3 Suspended Execution

Suppose we have, as an example of program to be debugged, a verb main which uses a supporting verb plus
```   main  =: 3 : 0
k =. 'hello'
z =. y plus k
'result is'; z
)

plus =: +
```
Clearly there is an error in main: the string k is inconsistent with the numeric argument expected by plus.

If we type, for example, main 1 at the keyboard, then when the error is detected the program terminates, an error-report is displayed and the user is prompted for input from the keyboard.

```   main 1
|domain error: plus
|   z=.y     plus k
```
To gather more information about the cause of the error, we can arrange that the program can be suspended rather than terminated when control returns to the keyboard. To enable suspension we use the command (13!:0) 1 before running main again.
```   (13!:0) 1
```
Now when main is re-run, we see a slightly different error message
```   main 1
|domain error: plus
|plus[:0]

```
At this point execution is suspended. In the suspended state, expressions can be typed in and evaluated. Notice that the prompt is 6 spaces (rather than the usual 3) to identify the suspended state.
```      1+1
2

```
We can view the current state of the computation, by entering at the keyboard this expression, to show (selected columns of) what is called the "execution stack".
```      0 2 6 7 8 { " 1 (13!:13 '')
+----+-+---------+----------+-+
|plus|0|+-+-----+|          |*|
|    | ||1|hello||          | |
|    | |+-+-----+|          | |
+----+-+---------+----------+-+
|main|1|+-+      |+--+-----+| |
|    | ||1|      ||k |hello|| |
|    | |+-+      |+--+-----+| |
|    | |         ||y |1    || |
|    | |         |+--+-----+| |
+----+-+---------+----------+-+

```
The stack is a table, with a row for each function currently executing. We see that plus is the function in which the error was detected, and plus is called from main.

The stack has 9 columns, of which we selected only 5 for display (columns 0 2 6 7 8). The columns are:

 0 Name of suspended function. Only named functions appear on the stack. 1 (not shown above) error-number or 0 if not in error 2 Line-number. plus is suspended at line 0 and main is at line 1 3 (not shown above) Name-class: 1 2 or 3 denoting adverb, conjunction or verb 4 (not shown above) Linear representation of suspended function 5 (not shown above) name of script from which definitions were loaded 6 Values of arguments. plus was called with arguments 1 and 'hello' 7 Names and values of local variables. plus being a tacit verb has no local variables, while main has k and also y, since arguments of explicit functions are regarded as local variables. 8 An asterisk, or a blank. plus is asterisked to show it is the function in which suspension was caused. Normally this the top function on the stack, (but not necessarily, as we will see below).

While in the suspended state we can inspect any global variables, by entering the names in the usual way. In this simple example there are none.

Finally, we can terminate the suspended execution, and escape from the suspended state, by entering the expression:

```   (13!:0) 1
```

## 29.4 Programmed Error Handling

By default, when suspension is enabled, and an error is encountered, the program suspends and awaits input from the keyboard.

We can arrange that instead of taking input from the keyboard, when an error is encountered, our own error-handling routine is automatically entered.

Suppose we decide to handle errors by doing the following:

• display the error message generated by the system
• display (selected columns of) the stack
• cut short the execution of the the suspended function, and cause it to return the value 'error' instead of whatever it was intended to return.
• resume executing the program. (This may or may not result in a cascade of further errors.)

Here is a verb to perform this sequence of actions:

```   handler =: 3 : 0
(1!:2&2) 13!:12 ''                  NB. display error message
(1!:2&2) 0 2 6 7 8 {" 1 (13!:13 '') NB. display stack
13!:6 'error'                       NB. resume returning 'error'
)
```
The next step is to declare this verb as the error-handler. To do this we set an appropriate value for what is called the "latent expression". The latent expression is represented by a string which, if non-null, is executed automatically whenever the system is about to enter the suspended state. The latent expression can be queried and set with 13!:14 and 13!:15. What is the current value of the latent expression?
```   13!:14 ''

```
A null string. We set the latent expression to be a string, representing an expression meaning "execute the verb handler".
```   13!:15 'handler 0'
```
Now we make sure suspension is enabled:
```   (13!:0) 1 NB. enable suspension
```
and try a debugging run on main
```   main 1
|domain error: plus
|plus[:0]

+-------+-+---------+---------+-+
|handler|1|+-+      |+-+-+    | |
|       | ||0|      ||y|0|    | |
|       | |+-+      |+-+-+    | |
+-------+-+---------+---------+-+
|plus   |0|+-+-----+|         |*|
|       | ||1|hello||         | |
|       | |+-+-----+|         | |
+-------+-+---------+---------+-+
|main   |1|+-+      |+-+-----+| |
|       | ||1|      ||k|hello|| |
|       | |+-+      |+-+-----+| |
|       | |         ||y|1    || |
|       | |         |+-+-----+| |
+-------+-+---------+---------+-+
+---------+-----+
|result is|error|
+---------+-----+
```
We see that the topmost stack-frame is for handler, because we are in handler when the request to view the stack is issued. The suspended function is plus.

The display result is error demonstrates that plus returned the value ('error') supplied by handler.

This is the end of Chapter 29.

The examples in this chapter were executed using J version j701/beta/2010-11-24/22:45. This chapter last updated 22 Dec 2010
Copyright © Roger Stokes 2010. This material may be freely reproduced, provided that this copyright notice is also reproduced.

>>  <<  Usr  Pri  JfC  LJ  Phr  Dic  Rel  Voc  !:  Help  Learning J