Hello,
Please give me a hint to understand the "do: separatedBy:" keyword
message used in ProfStef tutorial :
i) in Pharo version 12 :
https://ramix.org/pharo/ProfStef/iterators23.png
ii) in Pharo version 13 :
https://ramix.org/pharo/ProfStef/iterators25.png
--
Thanks for your help.
Rene Paul Mages (ramix) GnuPG key : 0x9840A6F7
https://sites.google.com/view/les-logiciels-libres/pharo
https://twitter.com/RenePaulMages
Le 18/09/2025 à 01:35, Rene Paul Mages (ramix) via Pharo-users a écrit :
Hello,
Please give me a hint to understand the "do: separatedBy:" keyword
message used in ProfStef tutorial :
i) in Pharo version 12 :
https://ramix.org/pharo/ProfStef/iterators23.png
ii) in Pharo version 13 :
I am using the FINDER to search do:separatedBy:
and also the BROWSER ( Method: Collection>>do:separatedBy: )
https://ramix.org/pharo/ProfStef/MethodCollection.png
but I don't understand the explanations.
Nota Bene :
I am rereading the chapter 9 (Collections) of Pharo_By_Example :
https://scg.unibe.ch/download/pharobyexample/PBE1-2010-02-01.pdf
--
Thanks for your help.
Rene Paul Mages (ramix) GnuPG key : 0x9840A6F7
https://sites.google.com/view/les-logiciels-libres/pharo
https://twitter.com/RenePaulMages
Hi - is this a homework question? While anyone here can tell you what it does - its probably more helpful to you to work through it and properly understand it.
You haven't shown what the output is when you try it - which will give you a clue. Equally - in Smalltalk, the names of selectors like: #do:separatedBy: convey meaning (which is why we like to use good names, that hint at what parameters do). Finally - have you looked at the implementation of the method? The nice thing about Smalltalk is that there is very little magic - you can see the code that runs for operations - including things like #ifTrue: . Why don't you position your cursor on #do: and press ctrl-m (or cmd-m - for show iMplementors - its also in the context menu). This will let you see the code and you should be able to work it out. For fun - try doing the same for: 3 = 3 ifTrue: [ 1 + 1]. Finally - its also worth understanding [1+1] + 1 (and why it gives an error) whereas: [1+1] value + 1 dosn't.
Hope this helps.
Tim
On Thu, 18 Sep 2025, at 12:35 AM, Rene Paul Mages (ramix) via Pharo-users wrote:
Hello,
Please give me a hint to understand the "do: separatedBy:" keyword
message used in ProfStef tutorial :
i) in Pharo version 12 :
https://ramix.org/pharo/ProfStef/iterators23.png
ii) in Pharo version 13 :
https://ramix.org/pharo/ProfStef/iterators25.png
--
Thanks for your help.
Rene Paul Mages (ramix) GnuPG key : 0x9840A6F7
https://sites.google.com/view/les-logiciels-libres/pharo
https://twitter.com/RenePaulMages
The ANSI Smalltalk standard has this to say:
do: operation separatedBy: separator
For each element of the receiver, operation is evaluated with the element
as the parameter.
Before evaluating operation the second and subsequent times, evaluate
separator.
Separator is not evaluated if there are no elements or after the last
element.
We could implement this in Collection like so:
do: doBlock separatedBy: separatorBlock
|started|
started := false.
self do: [:each |
started ifTrue: [separator value] ifFalse: [started := true].
doBlock value: each].
You can look at the actual source code by typing
do:separatedBy:
in a Playground (Workspace) and then typing Ctrl-M (show iMplementors).
The idea is simple enough: aCollection do: aBlock separatedBy:
separatorBlock
invokes (aBlock value: x1) ... (aBlock value: xn) where x1 ... xn are the
elements of aCollection, but between each pair of calls to aBlock there is
an invocation of (separatorBlock value).
A good thing to do after you have looked at the implementation(s) is to look
at how it's used. Type
do:separatedBy:
into a Playground and type Ctrl-N (show seNders). It's almost always
printing
or concatenating with a separator. And that is EXACTLY what is happening in
the ProfStef tutorial you show.
Let's take a simple example.
Suppose you have a string 'abcd'.
If you want to write /a/b/c/d
string do: [:each | aStream nextPut: $/; nextPut: each].
If you want to write a/b/c/d/
string do: [:each | aStream nextPut: each; nextPut: $/].
So far so good, there are exactly as many / writes as there are element
writes,
so they can go in the same block. But if you want to write a/b/c/d what do
you do?
Now you have one FEWER separator than elements.
string do: [:each | aStream nextPut: each] separatedBy: [aStream nextPut:
$/]
does the trick. You could of course bodge something together yourself,
BUT #do:separatedBy: is a well known idiom so it is much easier for people
to understand.
Another approach would have been
Collection >>
doFirst: firstBlock thenDo: otherBLock
|started|
started := false.
self do: [:each |
started ifTrue: [otherBlock value: each] ifFalse: [firstBlock value:
each. started := true]].
and then we could write
aString doFirst: [:first | aStream nextPut: first] thenDo: [:each |
aStream nextPut: $/; nextPut: each]
but that would involve code duplication, so we use #do:separatedBy: instead.
On Thu, 18 Sep 2025 at 11:35 AM, Rene Paul Mages (ramix) via Pharo-users <
pharo-users@lists.pharo.org> wrote:
Hello,
Please give me a hint to understand the "do: separatedBy:" keyword
message used in ProfStef tutorial :
i) in Pharo version 12 :
https://ramix.org/pharo/ProfStef/iterators23.png
ii) in Pharo version 13 :
https://ramix.org/pharo/ProfStef/iterators25.png
--
Thanks for your help.
Rene Paul Mages (ramix) GnuPG key : 0x9840A6F7
https://sites.google.com/view/les-logiciels-libres/pharo
https://twitter.com/RenePaulMages
Le 18/09/2025 à 10:30, Richard O'Keefe via Pharo-users a écrit :
Thank you Richard and Tim for your help.
The ANSI Smalltalk standard has this to say:
do: operation separatedBy: separator
For each element of the receiver, operation is evaluated with the element
as the parameter.
Before evaluating operation the second and subsequent times, evaluate
separator.
Separator is not evaluated if there are no elements or after the last
element.
I understand now.
We could implement this in Collection like so:
do: doBlock separatedBy: separatorBlock
|started|
started := false.
self do: [:each |
started ifTrue: [separator value] ifFalse: [started := true].
doBlock value: each].
You can look at the actual source code by typing
do:separatedBy:
in a Playground (Workspace) and then typing Ctrl-M (show iMplementors).
Ok.
The idea is simple enough: aCollection do: aBlock separatedBy:
separatorBlock
invokes (aBlock value: x1) ... (aBlock value: xn) where x1 ... xn are the
elements of aCollection, but between each pair of calls to aBlock there is
an invocation of (separatorBlock value).
Now I understand the idea.
A good thing to do after you have looked at the implementation(s) is to look
at how it's used. Type do:separatedBy:
into a Playground and type Ctrl-N (show seNders). It's almost always
printing or concatenating with a separator.
And that is EXACTLY what is happening in the ProfStef tutorial you show.
Perfect.
Let's take a simple example.
Suppose you have a string 'abcd'.
If you want to write /a/b/c/d
string do: [:each | aStream nextPut: $/; nextPut: each].
If you want to write a/b/c/d/
string do: [:each | aStream nextPut: each; nextPut: $/].
So far so good, there are exactly as many / writes as there are element
writes,
so they can go in the same block. But if you want to write a/b/c/d what do
you do?
Now you have one FEWER separator than elements.
string do: [:each | aStream nextPut: each] separatedBy: [aStream nextPut:$/]
does the trick. You could of course bodge something together yourself,
BUT #do:separatedBy: is a well known idiom so it is much easier for people
to understand.
It is clear now.
Another approach would have been
Collection >>doFirst: firstBlock thenDo: otherBLock
|started|
started := false.
self do: [:each |
started ifTrue: [otherBlock value: each] ifFalse: [firstBlock value:
each. started := true]].
and then we could write
aString doFirst: [:first | aStream nextPut: first] thenDo: [:each |
aStream nextPut: $/; nextPut: each]
but that would involve code duplication, so we use #do:separatedBy: instead.
Your explanation is very complete.
--
Thanks for your help.
Rene Paul Mages (ramix) GnuPG : 0x9840A6F7
https://renemages.wordpress.com/smalltalk/pharo
https://sites.google.com/view/les-logiciels-libres/pharo
https://twitter.com/RenePaulMages
Hi tim
Rene Paul is long time follower of Pharo. He is now a retired mathematician and this is nice to see
him coding in Pharo :)
S
On 18 Sep 2025, at 09:49, Tim Mackinnon via Pharo-users pharo-users@lists.pharo.org wrote:
Hi - is this a homework question? While anyone here can tell you what it does - its probably more helpful to you to work through it and properly understand it.
You haven't shown what the output is when you try it - which will give you a clue. Equally - in Smalltalk, the names of selectors like: #do:separatedBy: convey meaning (which is why we like to use good names, that hint at what parameters do). Finally - have you looked at the implementation of the method? The nice thing about Smalltalk is that there is very little magic - you can see the code that runs for operations - including things like #ifTrue: . Why don't you position your cursor on #do: and press ctrl-m (or cmd-m - for show iMplementors - its also in the context menu). This will let you see the code and you should be able to work it out. For fun - try doing the same for: 3 = 3 ifTrue: [ 1 + 1]. Finally - its also worth understanding [1+1] + 1 (and why it gives an error) whereas: [1+1] value + 1 dosn't.
Hope this helps.
Tim
On Thu, 18 Sep 2025, at 12:35 AM, Rene Paul Mages (ramix) via Pharo-users wrote:
Hello,
Please give me a hint to understand the "do: separatedBy:" keyword
message used in ProfStef tutorial :
i) in Pharo version 12 :
https://ramix.org/pharo/ProfStef/iterators23.png
ii) in Pharo version 13 :
https://ramix.org/pharo/ProfStef/iterators25.png
--
Thanks for your help.
Rene Paul Mages (ramix) GnuPG key : 0x9840A6F7
https://sites.google.com/view/les-logiciels-libres/pharo
https://twitter.com/RenePaulMages
Stéphane Ducasse
http://stephane.ducasse.free.fr
06 30 93 66 73
"If you knew today was your last day on earth, what would you do differently? ....ESPECIALLY if, by doing something different, today might not be your last day on earth.” Calvin & Hobbes
Hello Rene Paul
compare
| res |
res := OrderedCollection new.
#($a $b $c) do: [:aChar | res add: aChar].
res
an OrderedCollection($a $b $c)
| res |
res := OrderedCollection new.
#($a $b $c) do: [:aChar | res add: aChar; add: $,].
res
an OrderedCollection($a $, $b $, $c $,)
and
| res |
res := OrderedCollection new.
#($a $b $c) do: [:aChar | res add: aChar] separatedBy: [res add: $,].
res
an OrderedCollection($a $, $b $, $c)
On 18 Sep 2025, at 02:59, Rene Paul Mages (ramix) via Pharo-users pharo-users@lists.pharo.org wrote:
Le 18/09/2025 à 01:35, Rene Paul Mages (ramix) via Pharo-users a écrit :
Hello,
Please give me a hint to understand the "do: separatedBy:" keyword message used in ProfStef tutorial :
i) in Pharo version 12 :
https://ramix.org/pharo/ProfStef/iterators23.png
ii) in Pharo version 13 :
https://ramix.org/pharo/ProfStef/iterators25.png
I am using the FINDER to search do:separatedBy:
and also the BROWSER ( Method: Collection>>do:separatedBy: )
https://ramix.org/pharo/ProfStef/MethodCollection.png
but I don't understand the explanations.
Nota Bene :
I am rereading the chapter 9 (Collections) of Pharo_By_Example :
https://scg.unibe.ch/download/pharobyexample/PBE1-2010-02-01.pdf
--
Thanks for your help.
Rene Paul Mages (ramix) GnuPG key : 0x9840A6F7
https://sites.google.com/view/les-logiciels-libres/pharo
https://twitter.com/RenePaulMages
Stéphane Ducasse
http://stephane.ducasse.free.fr
06 30 93 66 73
"If you knew today was your last day on earth, what would you do differently? ....ESPECIALLY if, by doing something different, today might not be your last day on earth.” Calvin & Hobbes
Le 19/09/2025 à 20:47, stephane ducasse a écrit :
Hello Rene Paul
compare
| res |
res := OrderedCollection new.
#($a $b $c) do: [:aChar | res add: aChar].
res
an OrderedCollection($a $b $c)
| res |
res := OrderedCollection new.
#($a $b $c) do: [:aChar | res add: aChar; add: $,].
res
an OrderedCollection($a $, $b $, $c $,)
and
| res |
res := OrderedCollection new.
#($a $b $c) do: [:aChar | res add: aChar] separatedBy: [res add: $,].
res
an OrderedCollection($a $, $b $, $c)
All the best
Rene Paul Mages (ramix) GnuPG key : 0x9840A6F7
https://sites.google.com/view/les-logiciels-libres/pharo
https://twitter.com/RenePaulMages
Hi Rene Paul -I hope my reply wasn’t condescending. That wasn’t the intent, but we sometimes find that students are asking you to do their homework and rather than a directly answering, it’s more instructive to try and help them reason on the code - particularly as Smalltalk is a language where you can reason on the code.
Anyway, I hope the concept of how a BlockClosure works has got you hooked (it was the light bulb moment for me, many years ago - and I still marvel at it today - it’s so elegant).
Tim
On 19 Sep 2025, at 19:43, stephane ducasse stephane.ducasse@inria.fr wrote:
Hi tim
Rene Paul is long time follower of Pharo. He is now a retired mathematician and this is nice to see
him coding in Pharo :)
S
On 18 Sep 2025, at 09:49, Tim Mackinnon via Pharo-users pharo-users@lists.pharo.org wrote:
Hi - is this a homework question? While anyone here can tell you what it does - its probably more helpful to you to work through it and properly understand it.
You haven't shown what the output is when you try it - which will give you a clue. Equally - in Smalltalk, the names of selectors like: #do:separatedBy: convey meaning (which is why we like to use good names, that hint at what parameters do). Finally - have you looked at the implementation of the method? The nice thing about Smalltalk is that there is very little magic - you can see the code that runs for operations - including things like #ifTrue: . Why don't you position your cursor on #do: and press ctrl-m (or cmd-m - for show iMplementors - its also in the context menu). This will let you see the code and you should be able to work it out. For fun - try doing the same for: 3 = 3 ifTrue: [ 1 + 1]. Finally - its also worth understanding [1+1] + 1 (and why it gives an error) whereas: [1+1] value + 1 dosn't.
Hope this helps.
Tim
On Thu, 18 Sep 2025, at 12:35 AM, Rene Paul Mages (ramix) via Pharo-users wrote:
Hello,
Please give me a hint to understand the "do: separatedBy:" keyword
message used in ProfStef tutorial :
i) in Pharo version 12 :
https://ramix.org/pharo/ProfStef/iterators23.png
ii) in Pharo version 13 :
https://ramix.org/pharo/ProfStef/iterators25.png
--
Thanks for your help.
Rene Paul Mages (ramix) GnuPG key : 0x9840A6F7
https://sites.google.com/view/les-logiciels-libres/pharo
https://twitter.com/RenePaulMages
Stéphane Ducasse
http://stephane.ducasse.free.fr
06 30 93 66 73
"If you knew today was your last day on earth, what would you do differently? ....ESPECIALLY if, by doing something different, today might not be your last day on earth.” Calvin & Hobbes
Le 22/09/2025 à 10:42, Tim Mackinnon via Pharo-users a écrit :
Hi Rene Paul -I hope my reply wasn’t condescending. That wasn’t the intent, but we sometimes find that students are asking you to do their homework and rather than a directly answering, it’s more instructive to try and help them reason on the code - particularly as Smalltalk is a language where you can reason on the code.
Thank you Tim for your message.
Anyway, I hope the concept of how a BlockClosure works has got you hooked (it was the light bulb moment for me, many years ago - and I still marvel at it today - it’s so elegant).
Pharo is effectively a very_elegant language .
--
All the best
Rene Paul Mages (ramix) GnuPG : 0x9840A6F7
https://wiki.linux-azur.org/?PagePHARO
https://renemages.wordpress.com/smalltalk/pharo
https://sites.google.com/view/les-logiciels-libres/pharo