[ANSI-Smalltalk] Behaviour of #collect:

Richard O'Keefe ok at cs.otago.ac.nz
Wed Sep 24 05:54:08 BST 2008


On 23 Sep 2008, at 7:04 pm, Bruce Badger wrote:

> It seems that collect does not make sense in all cases and yet we are
> twisting and turning to make it fit.

No.

The underlying idea is

    map :: (Collection c1, Collection c2) => (a -> b) -> (c1 a) -> (c2  
b)

to use Haskell type syntax.   #collect: is normally used as if it were
map.  You give it a collection of inputs, you apply a block to each of
them, you get a collection of results.

Generally speaking, the exact kind of collection you get as a result
does not matter very much.  Unlike Haskell (and Ada), where the type
of an overloaded operation's result can be used to figure out which
version to use, Smalltalk can't do that.  So #collect: has to guess
what c2 should be.

The standard says to guess c2 == c1.  However, already in the standard,
that breaks down for Interval.  It also breaks down for  
SortedCollection.
One swallow doesn't make a summer, but two exceptions makes a pattern.
It is actually quite common for classes outside the standard to have to
return results of some other class.  (For example, my SortedSet returns
an Array because there's no reason to expect the results to be  
comparable
the way the original elements were.)

The question is how far you can go from the letter of the standard  
without
violating common sense.  Since existing practice is that dictionaries ->
dictionaries, sets -> sets, and sequences -> sequences, and the existing
violations of the "same type" rule in the standard are instances of
sequence -> sequence, it hardly seems like "twisting and turning" to
allow sequence -> sequence more generally.

>
>
> Perhaps specific intention revealing selectors are needed in some
> cases, and perhaps some objects should raise an exception when sent
>>> collect:

But #[0 1 2] and 'abc' (to use my running examples) *can* support
#collect:.  Indeed, by the standard they must.

I put it to you that for something like
	#[0 1 2] collect: [:each | each * 1000]
there is no more intention revealing selector than #collect:.

There is a special problem here.  I *can* detect whether I have been
given a collection.  I *can* detect whether all the elements are
integers.  But I *cannot* detect whether collections of that kind are
limited in some way.  Just because my examples have involved
standard classes does not mean that the issue is limited to them.
So my code can't *TELL* whether the usual #collect: will work or
whether some other method should be used.

The whole point of having an elaborate set of collection classes is
precisely so that you can write general-purpose code that DOESN'T HAVE
TO KNOW exactly what kind of collection it is working with.





More information about the ANSI-Smalltalk mailing list