A for-loop surprise
Mark S. Miller
markm@caplet.com
Sat, 08 May 1999 19:06:37 -0700
A sign of a good formalism is when it has more power, accessible simply, than its designer knew about. I have just been surprised this way by my own for loop. The for loop was built as an aid in enumerating thru an existing collection, but not for accumulating a result. For a silly example, let's say and we're ignorant of elementary algebra, but we want to sum the doubles of the numbers between 1 and 6 anyway:
? define accum := 0
? for i in 0..6 {
> accum += i*2
> }
? accum
# value: 42
While this is the ultimate answer, have we asked the ultimate question? The "for" part is very sweet for taking "0..6" apart, but can we do better putting the result together? Well, I'm not sure the result is better (from a software engineering viewpoint), but I'm not sure it's not.
First, we define a reusable abstraction for accumulating with "+":
? define sum(accum, collection) {
> define summer iterate(assocFunc) {
> for k => v in collection {
> accum += assocFunc(k, v)
> }
> accum
> }
> }
# value: <sum>
The we use it:
? for i in sum(0, 1..6) {
> i*2
> }
# value: 42
? for i in sum("", 1..6) {
> i*2
> }
# value: 24681012
? for i in sum([], 1..6) {
> [i*2]
> }
# value: [2, 4, 6, 8, 10, 12]
The expansion of the for-loop is shown on http://www.erights.org/elang/grammar/prim-expr.html#for and hasn't been changed to enable this new use. Anyone care to guess why the above surprise works?
More important, are abstractions like "sum" a good idea? Should they be encouraged?
Cheers,
--MarkM