[BUG] Set>>collect:
Andreas Raab
andreas.raab at gmx.de
Fri Feb 14 01:18:36 UTC 2003
Richard,
> Anyway, I think I have made my case for #collect:into:
Yes, but where's the code?! Properly prefixed with an [ENH][FIX] the
harvesters may actually have a chance to find it.
Cheers,
- Andreas
> -----Original Message-----
> From: squeak-dev-bounces at lists.squeakfoundation.org
> [mailto:squeak-dev-bounces at lists.squeakfoundation.org] On
> Behalf Of Richard A. O'Keefe
> Sent: Friday, February 14, 2003 2:12 AM
> To: squeak-dev at lists.squeakfoundation.org
> Subject: Re: [BUG] Set>>collect:
>
>
> Bill Spight <bspight at pacbell.net> wrote:
> This afternoon I watched a Set appear where I wanted an
> IdentitySet. The
> culprit seems to be here:
>
> [Set>>collect: has "Set new" not "self species new"]
>
> This is one I consider reporting a couple of years ago,
> and agonised over a bit. It finally dawned on me that the code
> as it stands is hard to improve.
>
> The reason it is hard to improve is PluggableSets.
>
> Suppose I have a PluggableSet of Strings, and the equality and
> hash blocks are such that alphabetic case is ignored. Call this
> "cis".
>
> Suppose further that "Set new" is changed to "self species new".
>
> What's "cis species"?
> It's PluggableSet.
>
> Now suppose I do "cis collect: [:each | each , each]".
> I get a PluggableSet, but it has a nil hashBlock and a nil equalBlock.
> Thanks to special case code in PluggableSet>>scanFor: that acts just
> like a Set. What I get is something that ACTS like a Set, but LOOKS
> like a PluggableSet.
>
> What we'd really need to make that example work the way I want is
> "self copyEmpty" not "self species new".
>
> But if it were fixed _that_ way, I'd be stuck when I did
> "cis collect: [:each | each length]", because now the hash and equal
> blocks would be trying to ignore alphabetic case in the characters of
> integers, which don't have characters to ask about.
>
> The essential point about #collect: is that the transformation block
> does NOT in general return objects of the same type that it is passed.
>
> Just because identity is the right individuation criterion for items
> x y in a set, that does not mean that it is the right individuation
> criterion for (someBlock value: x) and (someBlock value: y).
>
> In short, the code that is there in Set is just about the best
> compromise possible.
>
> Suppose instead that the code were factored like this:
>
> Set>>
> collect: aBlock
> ^self collect: aBlock into: Set new
>
> collect: aBlock into: aCollection
> array do: [:each |
> each ifNotNil: [
> aCollection add: (aBlock value: each)]].
> ^aCollection
>
> Then we could have
> aSet collect: aBlock into: IdentitySet new
> anIdentitySet collect: aBlock into:
> (PluggableSet new hashBlock: foo; equalBlock: bar; yourself)
> and a host of other combinations.
>
> #collect:into: makes a lot of sense for most collections (of course
> the last argument must be an extensible collection), e.g.
> aString collect: [:each | each asInteger] into: IdentitySet new.
> That could of course be done using
> IdentitySet new withAll: (aString collect: [:each | each
> asInteger])
>
> except that String>>collect: wants to make a String, and so this
> perfectly sensible operation doesn't work. FEH! The general rule
> is that a #collect: method should return a container with the same
> *shape* as the receiver, but not with the same *element restrictions*.
>
> Object>>
> isCharacter ^false
>
> Character>>
> isCharacter ^true
>
> String>>
> collect: aBlock
> "Answer a String or an Array depending on whether all of the
> values yielded by aBlock are Characters (String) or
> not (Array)."
> |result item flag t|
>
> result := self species new: self size.
> flag := false.
> 1 to: self size do: [:index |
> item := aBlock value: (self at: index).
> (flag or: [item isCharacter])
> ifFalse: [t := Array new: self size.
> 1 to: index - 1 do: [:i |
> t at: i put: (result at: i)].
> result := t.
> flag := true].
> result at: index put: item].
> ^result
>
> Without some such change, String>>collect: is essentially useless.
> Anyway, I think I have made my case for #collect:into:
>
>
More information about the Squeak-dev
mailing list
|