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.
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
exactly the same time as our program terminates.
Use a line of the form “
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
Raising an exception is similar to stopping
execution, in that it interrupts the control flow.
Use the verb “
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 ]
Use the verb “
generate” for functions, or “
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
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
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.