really silly question

Lex Spoon lex at cc.gatech.edu
Sun Sep 2 20:19:22 UTC 2001


John Hinsley <jhinsley at telinco.co.uk> wrote:
> > 
> > thirdArray := (1 to: firstArray size) collect: [:index |
> >         (firstArray at: index) + (secondArray at: index)]
> 
> Thanks Jon
> 
> I'm coming rapidly to the realisation that I find it very difficult to
> internalise iterations (and not only in Smalltalk!). 
> 
> I wonder how common this is?
> 

I've heard that in intro programming classes, loops are the place where
most students fall out.  if-then is fine, variables are okay, operations
are okay, and even (I think) subroutines are okay, but loops really kill
students off.  This matches my scant experience, as well, teaching an
occasional person how to program.

Loops are actually quite similar to recursive functions.  This sounds
strange, but consider.  The theoretical description of the meaning of a
loop is recursive -- do one loop, then do the test, then possibly recur.
 People who study small programs a lot  recommend studying loops in
terms of invariants plus movement towards a terminating condition --
pretty much the same as for recursive functions!  In fact, not only are
loops pretty similar to recursive functions, I think they may even be
harder: at least with the recursive function, the function name can help
you figure out the equivalent to an invariant ("gee, it says
sorted(x,1,n) -- guess the result will be x with elements 1..n sorted").
 With loops, you must reverse engineer the invariant.

Finally, I'll add my personal experience: I still find it tricky to add
a *new* kind of loop to my code.  Now, I can whip out a "iterate over
the elements and accumulate into a subsidiary array" very quickly, but
that's because I've seen this kind of loop a zillion times!  If the loop
has a structure that's new, I really have to think about it for a minute
or two, even after 15-20 years of programming (depending on how you
count).  It just so turns out that almost all loops are familiar ones,
so this isn't an issue for me in practice.  Perhaps other programmers
will introspect the same thing?

Anyway, now for the good news: Smalltalk allows you to get away from
low-level loop algorithms in almost all cases that occur in practice. 
The reason Smalltlak can do this, and many languages can't, is because
of the powerful combination of collections and blocks.  Consider this
wonderful response to the original question:

	firstArray with: secondArray collect: [ :a :b | a + b ]

Is this really a loop?  Technically, with:collect: is using a loop
internally, but cognitively, it just doesn't seem the same to me as a
hand-coded loop.  All the details of incrementing an index and moving
toward completion are left out, and it just looks like combining two
collections with an operation.  Smushing two collections together really
seems simpler to me than "start with element 1; do stuff with element i;
move to element i+1;" etc.  


By the way, there is a nice generalization of the above with:foo:
pattern.  It looks like this:

	(firstArray with: secondArray) collect: [ :combo | combo first + combo
second ]

This use of #with: (which doesn't currently exist), is identical to ML
and Haskel's "zip" function, and it allows you to use all of collect:,
select:, reject:, do:, detect:, etc. without writing with:collect:,
with:select:, with:reject:, etc.  In brief, the presence of a "with"
clause can be orthogonal to which collection operation is being used.


Overall, I'm really starting to think loops should be treated like 
assembly language or two's complement: interesting for the
terminally curious, probably useful to know a *little* about, but not
incredibly useful in most programs.  (Of course, this is only true in a
nice language that actually has collections and blocks!)

John, you're not at all alone.  :)


-Lex




More information about the Squeak-dev mailing list