7. Control structures

7.1. Structured programming

Languages in early days such as Fortran and COBOL use goto statement extensively, which results in obscure program structure. In 1968, Dijkstra insisted a program structure is more readable if it is a hierarchical composition of sequences, iterations and conditional branches.

Loop in early Basic and Pascal

10 X=1
20 IF X>=1000 THEN GOTO 60
30 PRINT X
40 X=X*2
50 GOTO 20
60 END
x = 1;
while x<1000 do
  begin
    writeln(x);
    x = x*2
  end;

7.2. Non-local exits

According to the idea of structured programming, it is not a good code to jump over block structures, but we sometimes want to write such code. For example, a return statement immediately exits from the function block even if it is in nested blocks.

Non-local exits is an enhanced version of return (and tamed version of goto) that terminates nested function calls at once and goes back to the outer level function.

Catch and throw in Ruby

def bar
  throw :a, 3
end

def foo
  bar
end

catch(:a) do
  foo
end

7.3. Exceptions

7.3.1. What is exception?

In early languages, if something unusual occurs during execution, the program has no choice but to stop with an error message. Recent languages can deal with such situation more gracefully.

An exception is an unusual event in a program for which we need some extra processing.

  • Detected by hardware: division by zero, to read or write protected memory, end of file, etc.

  • Detected by software: index of an array is out of range, etc.

  • Defined by programmers: anything you wish.

7.3.2. Exception handling

Even if a language has no exception handling mechanism, it is possible to write a program that deal with unusual events. However, exception handling is more convenient in the following way:

  • No need to write codes for detecting exceptions. Imagine if you need to check that the divisor is not equal to 0 before every division.

  • Cleaner code for dealing with an unusual event, especially when it requires non-local exits.

  • Managing several exceptions in one place.

An exception handler is a part of program that is invoked when an exception occurs.

Exception handling in PL/I

An exception handler can be written in anywhere in the program with the ON statement. For example, the following is a handler for an exception SUBSCRIPTRANGE, which occurs when an index of an array is out of range.

ON SUBSCRIPTRANGE
  BEGIN;
    PUT LIST ('ERROR') SKIP;
  END;

Note that the ON statement is an executable statement (not a declaration), which means bindings between exceptions and exception handlers are dynamic. An exception handler is valid after an ON statement is executed, and until another ON statement with the same exception name is executed.

In addition, in order to make an execption handler valid, we need to write an exception name before a part of the program in which the exception may occur. For example, the following code checks the index I if it is out of range or not.

(SUBSCRIPTRANGE):
  BEGIN;
    A = B(I);
  END;

Exception handling in Java

  • An exception is represented by an instance of an exception class, which is passed to a handler as an argument.

  • Exception classes are hierarchical. An execption handler can deal with many kinds of exceptions by specifying a high level exception class in the hierarchy.

  • Bindings between exceptions and exception handlers are lexical. try-catch-finally statement makes the scope of handlers.

    try {
        FileWriter x = new FileWriter("sample.txt");  // IOException may occur
    } catch (IOException e) {
        e.printStackTrace();
    }
    
  • By declaring throws at the head of a method, an exception can be propagated to the calling method, which allows dynamic bindings between exceptions and exception handlers.

    static void bar() {
        try {
            foo();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    static void foo() throws IOException {
        FileWriter x = new FileWriter("sample.txt");
    }
    
  • If there is a possibility of an exception, programmers must either write an exception handlers or propagate it. The aim of this rule is to make programs robust in unexpected situations.

Excercise 15

Java forces programmers to handle exceptions, but that is not the case for Error and RunTimeException. Guess the reason.

[Answer]