[squeak-dev] #doWhileTrue: (was: The Trunk: System-nice.1149.mcz)

Levente Uzonyi leves at caesar.elte.hu
Tue Apr 7 13:19:17 UTC 2020


Hi Christoph,

On Tue, 7 Apr 2020, Thiede, Christoph wrote:

> 
> > There is no syntax for blockReturn because it wouldn't be possible to use it.
> 
> 
> What do you mean? Here is an ugly but working example of "continue" in Smalltalk - provided that the block is not inlined:

You're just abusing a compiler flaw there. IMO, the compiler should 
deoptimize any block referencing thisContext.
So, your "continue" is not general purpose at all. It can only be used 
inside non-inlined blocks (hence your use of #to: and #do: instead of 
#to:do:). And, it can only be used from inlined blocks (the argument of 
#ifFalse: in your example).


Levente

> 
> (1 to: 10) do: [:i |
> | j |
> i even ifFalse: [thisContext return].
> j := i squared.
> Transcript showln: i squared].
> 
> However, I agree that you should never use this in practice, it's too confusing. ;-)
> 
> Best,
> Christoph
> 
> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________
> Von: Squeak-dev <squeak-dev-bounces at lists.squeakfoundation.org> im Auftrag von Levente Uzonyi <leves at caesar.elte.hu>
> Gesendet: Montag, 30. März 2020 23:04:18
> An: The general-purpose Squeak developers list
> Betreff: Re: [squeak-dev] #doWhileTrue: (was: The Trunk: System-nice.1149.mcz)  
> Hi Christoph,
> 
> On Mon, 30 Mar 2020, Thiede, Christoph wrote:
> 
> >
> > Hi Nicolas,
> >
> >
> > I don't see your point of #doWhileTrue: being not idiomatic. What exactly do you mean by that except for "unfamiliar"?
> >
> >
> > However, I agree that the names are confusing, compared to #whileTrue: etc.
> >
> > +1 for naming them #repeatWhile: and #repeatUntil: instead!
> >
> >
> > > But that still means that we have two ways to express exactly the same thing, which by first principle should not be
> >
> > > (economy of implementation, of tests, of documentation, etc... small is beautiful !).
> >
> > Well, that's another a question of semantics, again. :) Remember my examples about #ifNotNil:/#==> etc.? Convenience methods support ease of writing and reading.
> >
> > > Really, not kidding?
> > The example is taken from BookMorph >> #saveOnUrlPage:. I did not read it in context, too ^^
> >
> > > Is the following better? > 
> > > [newPlace := self getNewPlace.
> > > file:= ServerFile new fullPath: newPlace.
> > > file exists] whileTrue
> >
> > In my opinion, #repeatUntil: would still be better :)
> >
> > > Note that I did not add non local block return in the middle of the block... > It was in the original method, doWhileTrue did not solve it.
> >
> > I was referring to blockReturn in the bytecode sense. Here is another example of confusing blockReturns:
> >
> > (foo satisfiesSomeCondition or: [|baz|
> >     baz := bar asBaz.
> >     foo cacheDuring: [
> >         baz satisfiesSomeOtherCondition]])
> >             ifTrue: [...]
> >
> > Hard to follow the control flow, isn't it? If I have the choice, I avoid these statements and use blocks,
> 
> Whether or not the above example is okay or not depends on what [...] is.
> For example, if it's simply ^self, then the use of #or: is unnecessary and
> the computation which reduces legibility can be moved out to the main flow
> of the method.
> 
> > either) to pass a piece of code to another object and compose control flows,
> > or) to explicitly pass a value to be evaluated lazily.
> > Both at once can be confusing. I think there is a good reason why there is no syntax for blockReturn like we have one for methodReturn (^).
> 
> There is no syntax for blockReturn because it wouldn't be possible to use it.
> 
> 
> Levente
> 
> >
> > Best,
> > Christoph
> >
> >________________________________________________________________________________________________________________________________________________________________________________________________________________________________
> _
> > Von: Squeak-dev <squeak-dev-bounces at lists.squeakfoundation.org> im Auftrag von Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>
> > Gesendet: Montag, 30. März 2020 20:56:43
> > An: The general-purpose Squeak developers list
> > Betreff: Re: [squeak-dev] #doWhileTrue: (was: The Trunk: System-nice.1149.mcz)  
> >
> >
> > Le lun. 30 mars 2020 à 19:58, Thiede, Christoph <Christoph.Thiede at student.hpi.uni-potsdam.de> a écrit :
> >
> >       Hi Nicolas,
> >
> >
> >       > There is no other sender of doWhileFalse: doWhileTrue: and my advice would be to deprecate them. YAGNI.
> >
> >
> > So my image actually contains around two dozen senders of #doWhileTrue: and #doWhileFalse: (Squot, Pheno and some of my own code). As mentioned somewhere else in the past, I actually like them and find them very useful.
> >
> > In my opinion, many senders of #whileTrue and #whileFalse should be refactored to use #doWhileTrue:/#doWhileFalse:. Here is a random example:
> >
> > [newPlace := self getNewPlace.
> > dir := ServerFile new fullPath: newPlace.
> > (dir includesKey: dir fileName)] whileTrue.
> >
> > I find that's ugly and counter-intuitive! I would rewrite this in the following way:
> >
> > [newPlace := self getNewPlace.
> > dir := ServerFile new fullPath: newPlace]
> >     doWhileTrue: [dir includesKey: dir fileName].
> >
> >
> > The first thing that upsets me is that they are not idiomatic. #whileTrue: and in a lesser way #whileTrue are.
> > The second thing that upsets me is that the names are REALLY too close to #whileTrue:
> > So at first, I was confused by the fact that they looked like synonyms.
> > Then I wondered exactly the same, what the hell has to be true?
> > Especially when the sole sender in trunk is [] doWhileTrue: true ;)
> >
> > IMO, they might be better spelled #repeatWhile: and #repeatUntil:
> > But that still means that we have two ways to express exactly the same thing, which by first principle should not be
> > (economy of implementation, of tests, of documentation, etc... small is beautiful !).
> >
> > We might discuss which is more readable, maybe
> >
> > [newPlace := self getNewPlace.
> > dir := ServerFile new fullPath: newPlace]
> >     repeatWhile: [dir includesKey: dir fileName].
> >
> > is more revealing than:
> >
> > [newPlace := self getNewPlace.
> > dir := ServerFile new fullPath: newPlace.
> > (dir includesKey: dir fileName)] whileTrue.
> >
> > IMO, it's a biased example, because the whole snippet is un-comprehensible.
> > So a ServerFile behaves like a ServerDirectory (from which it inherits...), oh nice (???).
> > And a ServerFile which would includes some item with same name as itself would mean that the file already exists...
> > Really, not kidding?
> >
> > So IMO that's what makes the snippet illegible, not whileTrue.
> > Is the following better?
> >
> > [newPlace := self getNewPlace.
> > file:= ServerFile new fullPath: newPlace.
> > file exists] whileTrue
> >
> > Anyway, the second one is there for such a long time that you can't expunge it that easily. It's idiomatic...
> >
> > The latter just reads easier. blockReturns in multi-statement blocks are not really intuitive.
> >
> >
> > Note that I did not add non local block return in the middle of the block...
> > It was in the original method, doWhileTrue did not solve it.
> >
> >       In the first version, when scanning the method quickly, I read "okay, something with places and directories is done, while true ...," I wonder "what has to be true?" and have to look back to the end of the block
> >       and find the beginning of the last statement.
> > But in the second version, I read "okay, something with places and directories is done, while that directory matches this specific condition." This version directly draws my attention to the important condition.
> >
> > Happy to hear your counterarguments :-)
> >
> > Best,
> > Christoph
> >
> >________________________________________________________________________________________________________________________________________________________________________________________________________________________________
> _
> > Von: Squeak-dev <squeak-dev-bounces at lists.squeakfoundation.org> im Auftrag von commits at source.squeak.org <commits at source.squeak.org>
> > Gesendet: Montag, 30. März 2020 12:51 Uhr
> > An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org
> > Betreff: [squeak-dev] The Trunk: System-nice.1149.mcz  
> > Nicolas Cellier uploaded a new version of System to project The Trunk:
> > http://source.squeak.org/trunk/System-nice.1149.mcz
> >
> > ==================== Summary ====================
> >
> > Name: System-nice.1149
> > Author: nice
> > Time: 30 March 2020, 12:50:26.196366 pm
> > UUID: ece53b0b-24d2-4d4b-bc91-6794a661f886
> > Ancestors: System-ul.1148
> >
> > avoid neuron storming [...] doWhileTrue: true, it just means [...] repeat
> >
> > There is no other sender of doWhileFalse: doWhileTrue: and my advice would be to deprecate them. YAGNI.
> >
> > =============== Diff against System-ul.1148 ===============
> >
> > Item was changed:
> >   ----- Method: MOFile>>searchByHash: (in category 'experimental') -----
> >   searchByHash: aString
> >          | hashValue nstr index incr key |
> >          hashValue :=  self hashPjw: aString.
> >          incr := 1 + (hashValue \\ (hashTableSize -2)).
> >          index := (hashValue \\ hashTableSize) .
> >          [        nstr := (hashTable at: index +1 ).
> >                  nstr = 0 ifTrue: [^nil].
> >                  key := self originalString: nstr.
> >                  key = aString ifTrue: [^self translatedString: nstr].
> >                  index >= (hashTableSize - incr)
> >                                  ifTrue: [index := index - (hashTableSize - incr)  ]
> >                                  ifFalse:[index := index + incr].       
> > +        ] repeat!
> > -        ] doWhileTrue: true.!
> >
> >
> >
> >
> >
> 
>


More information about the Squeak-dev mailing list