[ANSI-Smalltalk] Behaviour of #collect:
Richard O'Keefe
ok at cs.otago.ac.nz
Fri Sep 26 04:25:30 BST 2008
On 25 Sep 2008, at 9:40 pm, Andres Valloud wrote:
> Or this?...
>
> 'abc' collect: [:x | x codePoint] into: Array
Four flaws with this.
(1) Collecting "into" something generally means collecting
into an existing collection, not collecting into a class.
This will certainly conflict with existing libraries that
have a #collect:into: method.
My own library used to distinguish between #collect:into:
(existing object) and #collect:intoNew: (new instance of
class), before I junked them as too difficult to get right.
Implementing <class> withAll:collect: turned out to be far
less work, and far easier to use.
Compare a corrected version of this,
s := 'abc'.
s collect: [:x | x codePoint] into: (Array new: s size)
with
Array withAll: 'abc' collect: [:x | x codePoint].
(2) How does collect:intoNew: (assuming the name to be fixed)
know what message to send to the class? #new: is _not_
always the right thing to use.
(3) What happens if the Class argument is not a collection class?
'abc' collect: [:x | x codePoint] into: Socket
With <class> withAll: <collection> collect: <block>,
collections that aren't collection classes just don't implement
the method; end of story. They also know how to make themselves
big enough.
(4) What if you want to create a read-only collection?
This was the killer issue for me: I have ReadOnlyArray,
ReadOnlyByteArray, ReadOnlyBooleanArray, and ReadOnlyString,
and was thinking of introducing more read-only classes.
It was the ANSI standard's insistence that literal arrays and
strings were read-only that decided me to create some classes
that they could belong to. I have come to value ReadOnlyString
highly. Now I *can* do
ReadOnlyString withAll: #(65 66 67)
collect: [:each | Character codePoint: each]
because ReadOnlyString is in charge; it can decide exactly how to
do this, and can do whatever it would have done for #withAll:.
But it *can't* be done from the outside. That's the nature of
the read-only beast.
Many of these issues boil down to the quintessential question in
placing any Smalltalk method: Which object should be in charge?
Which has the knowledge? Which is _able_ to do the operation?
I am aware of collect-into in Common Lisp, and have used it, which
is why I first tried that in Smalltalk myself. That was when I
remembered why I stopped using it in Lisp.
More information about the ANSI-Smalltalk
mailing list