The difference in behaviour is exactly what I would expect.
I can't think of any way to make
aSet collect: collectBlock thenDo: doBlock
act identically to
(aSet collect: collectBlock) do: doBlock
without creating an intermediate set.
Here, for example, is the definition in Smalltalk/X,
with comments removed for brevity.
collect:collectBlock thenDo:aBlock
������ self do:[:each | aBlock value:(collectBlock value:each)].
(The lack of spaces after keywords is ST/X convention.)
Another way to express this would be with a function composition
combinator:
aSet do: (collectBlock before: doBlock).
aSet do: (doBlock after: collectBlock).
Note, by the way, that Set>>collect: has always been something
to approach with vigilant trepidation.�� Given Set, IdentitySet,
and PluggableSet, there is in general no reason to expect that
the receiver's notion of equality is approach for the results
of the collectBlock.�� That's why my library lets me write
�� Set withAll: collection collect: collectBlock
�� IdentitySet withAll: collection collect: collectBlock
�� (PluggableSet equalBy: equality hashBy: hasher) withAll: collection collect: collectBlock
�� (PluggableSet accordingTo: equivalence) withAll: collection collect: collectBlock
So in the case of
�� aSet collect: collectBlock thenDo: doBlock
there is no reason to expect aSet to know how to tell when two
collectBlock results should be regarded as equivalent.�� Seriously,
how is aSet supposed to know what collectBlock thinks equivalence
looks like?