[net.lang] Generators & Iterators -- Generators in Icon

whm@arizona.UUCP (01/23/84)

Since somebody mentioned generators in Icon, let me say a little more
about them.  In Icon, generators are not restricted to only appear in
certain control structures, rather, the ability to generate more than
one value is an attribute associated with certain expressions.  The
expression:

	1 to 10
	
generates the integers from 1 to 10.  A generator can be exhaustively
evaluated using the "every" control structure.  For example,

	every i := 1 to 10 do
		write(i)
		
writes out the integers from 1 to 10.  Note that the same thing can be
more idiomatically expressed as:

	every write(1 to 10)
	
Another generative operator is !, which generates elements of various
data objects.  If x is a list, then !x generates the elements of the
list; if x is a string, then !x generates the characters in the string.
For example,

	every write(!&lcase)
	
writes out the lower case letters, one per line.

Icon procedures have the ability to be generators.  Consider a procedure
that accepts a list as a parameter and generates the elements of the
list that are lists.  This can be expressed as:

	procedure lgen(lst)
	    every e := !lst do
		if type(e) == "list" then
		    suspend e
	end
	
Such a procedure could be used with:

	every lst := lgen(x) do
		...

Icon has a notion of "no result" for expressions which can be used in
conjunction with generators.  For example, the expression:

	1 > 2
	
"fails", i.e., it produces no result.  The expression:

	write(1 > 2)

produces no result because the comparison produces no result and the
write function is never called.  Icon tries to produce a result for all
expressions and when an expression fails, Icon looks for generators in
the expression that can be resumed so as to try another alternative.
Consider the problem of writing out all values in a list x (of integers)
that are larger than 100.  This can be expressed by:

	every write(100 < !x)
	
Each element in x is generated in turn and compared to 100.  If the
comparison succeeds, its value is the right-hand argument, which is
the value from the list, and this value is printed.  If the comparison
fails, no result is available for write, and it fails.  Because the
write expression is the object of an every, the generator !x is resumed.
This process continues until all suitable elements have been printed.
Note that if the expression were just:

	write(100 < !x)
	
the first element in x greater than 100 (if any) would be printed.


We (the University of Arizona CS Department) distribute Icon systems for
VAX and PDP-11 UNIX, and VAX/VMS for a nominal fee ($0 if you supply
a tape); contact me if you'd like more information.

					Bill Mitchell
					whm.arizona@rand-relay
					{kpno,mcnc,utah-cs}!arizona!whm