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?

On Sun, 8 Sep 2019 at 03:22, Herby Voj����k <herby@mailbox.sk> wrote:
Hello!

----
�� ��(#(1 2 3) asSet collect: #odd)
�� �� ��do: [ :each | Transcript show: each; cr ]

�� ��> true
�� ��> false

----

�� ��#(1 2 3) asSet collect: #odd
�� �� ��thenDo: [ :each | Transcript show: each; cr ]

�� ��> true
�� ��> false
�� ��> true
----


Bug or feature?

Herby