Dyaln Design Notes

#29: For Loops	(Change)

Version 1, January 1994
Copyright (c) 1993-1994, Apple Computer

This Design Note unifies Dylan's existing iteration constructs, for, 
for-each, and dotimes, into one general for statement.  It also changes 
the keywords in <range> to be compatible with the numeric clauses in the 
new for statement.

-------------------------------------------------------------------

For statement

Replace the for, for-each, and dotimes macros with the following general 
iteration construct:

for (clauses [{until | while} end-test]) 	[Special Form]
	body-forms 
	[finally result-forms] 
end
=> values

for allows any number of clauses.  Each clause controls one iteration 
variable throughout the iteration.  The optional end-test controls 
whether the iteration continues or terminates.  It does not control any 
iteration variables.

The kinds of clauses allowed in a for statement include the following:

Explicit step clauses provide the functionality of the old for statement.  
The syntax for an explicit step clause is as follows:

{variable | variable :: type} = init-value then next-value

Collection clauses provide the functionality of the old for-each 
statement.  The syntax for a collection clause is as follows:

{variable | variable :: type} in collection

Numeric clauses provide a convenient shorthand for iterating over 
integers.  The syntax for a numeric clause is as follows:

{variable | variable :: type} from start 
	[{to | above | below} bound]
	[by increment]

Iteration with for proceeds through the following steps:

1) 	Evaluate the expressions that are evaluated just once, in left to 
	right order as they appear in the for statement.

        For explicit step clauses, these expressions are type and 
	init-value.  

        For collection clauses, these expressions  are type and 
	collection.  If the value of collection is not a collection,
	signal an error.

        For numeric clauses, these expressions are type, start, bound if 
	it is supplied, and increment if it is supplied.  If increment
	is not supplied, it defaults to 1, or -1 if it is an above clause.

2)	Bind the iteration variables of explicit step and numeric clauses.  
        
	For each explicit step clause, bind variable to the value of 
	init-value.  If type is supplied and the value of init-value
	is not of the specified type, signal an error.

        For each numeric clause, bind variable to the value of start.  If 
	type is supplied and the value of start is not of the
	specified type, signal an error.

3)	Check numeric and collection clauses for exhaustion.  If a clause is 
	exhausted, go to step 9.

        A collection clause is exhausted if its collection has no next 
	element.  (The first time through, the "next element" is the
	first, if any.)

        Numeric clauses cannot be exhausted if bound is not supplied.  If 
	bound is supplied, the following table gives the conditions
	for exhaustion:

	                  increment >= 0        increment < 0
	keyword =  to     variable > bound      variable < bound
	keyword =  above  variable <= bound     variable <= bound
	keyword =  below  variable >= bound     variable >= bound

4)	Bind the iteration variables of collection clauses.  Fresh bindings 
	are created each time through the iteration.

        For each collection clause, bind variable to the next element of 
	the collection for that clause.  If type is supplied and this
	next element of the collection is not of the specified type,
	signal an error.

5) 	If end-test is supplied, evaluate it.  The termination conditions 
	depend on the symbol used to introduce the end-test in the for
	statement.

        If the value of end-test is false and the symbol is while, go to 
	step 9.  

        If the value of end-test is true and the symbol is until, go to 
	step 9.

6) 	Execute the body-forms in sequence.

7) 	Obtain the next values for explicit step and numeric clauses.
	Values are obtained in left to right order, in the environment
	produced by step 6.

        For each explicit step clause, evaluate next-value.

        For each numeric clause, add the values of variable and 
	increment.

8)	Bind the iteration variables of explicit step and numeric
	clauses to the values obtained in step 7.  For each clause, if
	type is supplied and the next value for that clause is not of
	the specified type, signal an error.  Fresh bindings are
	created each time through the iteration.  After variables are
	bound, go to step 3.

9) 	Evaluate the result-forms in sequence.  Bindings created in step 2 
	and 8 are visible during the execution of result-forms.
	Bindings created in step 4 (i.e. the iteration variables of
	collection clauses) are not visible during the execution of
	result-forms.  The values of the last result-form are returned
	by the for statement.  If there are no result-forms, #f is
	returned.

Range keyword arguments

Remove the up-to and through keyword arguments in range and add three 
arguments, to, above and below, which constrain the range.  to is an 
inclusive bound, above is an exclusive lower bound and below is an 
exclusive upper bound.  above and below constrain the range independent 
of the sign of by.

-------------------------------------------------------------------

Notes

Major changes between this specification and the Dylan book's iteration 
constructs:

        Various kinds of iteration clauses (general iteration clauses, 
numeric iteration clauses, and clauses for iterating over collections) 
are allowed to appear in the same construct.

        Since clauses themselves can cause the iteration to terminate 
(for example, when a collection is exhausted), the end test is moved into 
the clauses and becomes an optional "termination clause."

        Optional result expressions are separated from the end test.  
They now appear at the end of the construct rather than in the middle.

        Types may be declared for iteration variables.
