2014-11-27 9:21 GMT+01:00 Frank Lesser frank-lesser@lesser-software.com:
hmm ( Set withAll: #( 1 -1 )) collect: [ : e | e abs ] a Set(1)
IMO, these snippets have no sense... In somes cases, we will want to preserve uniqueness, in some cases we will want to preserve the size... #collect:as: answers to most use cases, explicitely.
Answering an Array is a bit against the current trend which is to preserve as far as possible the collection properties when selecting/collecting. For example, Dictionary collect: now answer a Dictionary, what it did not in the past. In most cases (except maybe Interval) this is possible when selecting, but not necessarily when collecting due to restrictions on element type (ByteArray WordArray String IdentitySet...), or due to Identity or non weak-references properties that have absolutely no guaranty to be preserved once transformed. Note that #species was originally used for both selecting and collecting, but we started to distinguish these two, that might be the reason for the current non-uniformity of its usage. Some collection change of species when collecting, some other just fail, obviously because we expect aString collect: #asUppercase to answer a String, not an Array... In all these cases, collect:as: is a generic answer.
Anyway, a 1-to-1 mapping with something unordered is quite useless... How are we going to map elements of the transformed collection with the original? We cannot iterate like this: (aSet with: anOrderedCollection do: [:a :b | ]), nor with a Stream or any sequenceable protocol on an unordered collection.
The only guaranty you have is that the block will be evaluated once with each item (if there is no block return or exception raised...). Even this expectation might be questionable, I once suggested to iterate only once per different value in a Bag, or once per run in a RunArray when collecting/selecting... i did not, because too many code rely on the side effects like | i | i := 0. aSet collect: [:each | i := i + 1. each transformWithRank: i]. IMO, this is bad style.
Nicolas
-----Ursprüngliche Nachricht----- Von: squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org] Im Auftrag von Bert Freudenberg Gesendet: Donnerstag, 27. November 2014 08:57 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] IdentitySet>>collect:
On 27.11.2014, at 02:23, Florin Mateoc florin.mateoc@gmail.com wrote:
On 11/26/2014 7:14 PM, Levente Uzonyi wrote:
Your example hides the problem of ordering - what Tobias is asking about
- so here's another:
(IdentitySet withAll: #(1 1.0)) collect: [ :each | each class ]
If IdentitySet >> #collect: were returning an Array, then what would be
the answer?
{ SmallInteger. Float } or { Float. SmallInteger } ?
snip
Levente
Then why does Dictionary>>keys return an Array? Where does the order come
from in that example?
Similarly, where does the order come from when you invoke collect:as: on
a set with Array as an argument?
The answer is quite simple: it is the iteration order. collect: is part
of the _iteration_ protocol.
I agree with Frank here, for me a more important aspect of collect: is
preserving the _mapping_ between the original
elements and the collected values. There is no obvious mapping if there are fewer collected values than
elements.
Florin
I agree. The order is unimportant, it's a Set after all. What *is* important is getting a collection of the same size back - by default. For other needs we have collect:as:.
- Bert -