Next / Previous / Contents / Shipman's homepage

5.5. Special forms for intended functions

Some program semantics don't fit the model of changes to a state item. Here are some exceptions and suggestions as to how to write their intended functions.

Program termination

If a program terminates, that's a rather important operation! Here's an example. Quite often, the first thing a script will do is to process and check the command line arguments. If they aren't valid, there is no point in continuing execution. Here is an example of an intended function for that process.

    # [ if the command line arguments are valid ->
    #     args  :=  an argparse.Namespace instance representing
    #               the values of those arguments
    #    else ->
    #     sys.stderr  +:=  (usage message) + (error message)
    #     stop execution ]

The last line above has no “:=” in it, but it's pretty important. Still, the idea of parallel execution of all the state changes holds: conceptually, our usage and error messages get sent to sys.stderr at exactly the same time as our program terminates.

Function return

Use a line of the form “return E” where E is a description of the return value. For a Python function that falls off the bottom, or whose return does not state a value, use “return None”.

Exceptions

Raising an exception is similar to stopping execution, in that it interrupts the control flow. Use the verb “raise”. Any other lines of the intended function are conceptually executed simultaneously with the raising of the exception. Here's an example.

    # [ if x >= 0 ->
    #     return the square root of x
    #   else ->
    #     sys.stderr  +:=  (error message)
    #     raise ValueError ]
Generators

Use the verb “generate” for functions, or “yield” for yield statements. Here is an example:

def updown(n):
    ''' [ n is a nonnegative integer ->
            generate the sequence 0, 1, 2, ..., n, n-1, n-2, ..., 0 ]
    '''
    #-- 1
    # [ generate 0, 1, 2, ..., n-1 ]
    for k in range(n):
        yield k

    #-- 2
    # [ generate n, n-1, n-2, ..., 0 ]
    for k in range(n, -1, -1):
        yield k

5.5.1. Terminal special forms

In the case of all the special forms described in Section 5.5, “Special forms for intended functions”, except for the “generate” and “yield” forms, execution does not fall through to the code that follows that prime.

  • If the prime is a function return, execution continues in the caller after the point where the function was called.

  • If the prime terminates execution, nothing executes after that prime.

  • If the prime raises an exception, execution may pass to a try-except construct at some higher level, or, if there is no handler for that exception, execution terminates.

We call such special forms terminal special forms because they may make the following code unreachable. This will be an issue during construction of trace tables.