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.! |
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].
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 <[hidden email]> im Auftrag von [hidden email] <[hidden email]>
Gesendet: Montag, 30. März 2020 12:51 Uhr An: [hidden email]; [hidden email] 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.!
Carpe Squeak!
|
Le lun. 30 mars 2020 à 19:58, Thiede, Christoph <[hidden email]> a écrit :
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...
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 reply to this post by Christoph Thiede
Hi Christoph,
On Mon, 30 Mar 2020, Thiede, Christoph wrote: > > 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]. And yeah, I would never ever use it in a method. Not just because it's redundant, as you pointed out above, but because the name is confusing: do what while what's true? > > The latter just reads easier. blockReturns in multi-statement blocks are not really intuitive. > 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. Couldn't disagree more with that. It's exactly the other way around. If you know the language, you know that a block returns its last statement's value, so you know what has to be true in case of #whileTrue. But the language tells you nothing about how #doWhileTrure: works. The name is just confusing (see above). Levente > > Happy to hear your counterarguments :-) > > Best, > Christoph > > _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ > Von: Squeak-dev <[hidden email]> im Auftrag von [hidden email] <[hidden email]> > Gesendet: Montag, 30. März 2020 12:51 Uhr > An: [hidden email]; [hidden email] > 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.! > > > > |
In reply to this post by Nicolas Cellier
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,
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 (^).
Best,
Christoph
Von: Squeak-dev <[hidden email]> im Auftrag von Nicolas Cellier <[hidden email]>
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 <[hidden email]> a écrit :
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...
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.
Carpe Squeak!
|
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, 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 <[hidden email]> im Auftrag von Nicolas Cellier <[hidden email]> > 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 <[hidden email]> 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 <[hidden email]> im Auftrag von [hidden email] <[hidden email]> > Gesendet: Montag, 30. März 2020 12:51 Uhr > An: [hidden email]; [hidden email] > 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.! > > > > > |
Le lun. 30 mars 2020 à 23:04, Levente Uzonyi <[hidden email]> a écrit : Hi Christoph, idiomatic: using, containing, or denoting expressions that are natural to a native speaker. So whileTrue: is natural for a native Smalltalker (I don't know a lot of natives, it's not my first programming language neither, but you get it). #whileTrue should not be considered independently of the more powerful #whileTrue: This later construct is not easily found in other languages where I often have to insert a if/break/continue/cycle which is much less expressive. Normally, you learn #whileTrue: which has many more senders, then once learned, #whileTrue. shouldn't sound un-natural.
I didn't even notice the presence of doWhileTrue: until today! I just stumbled upon it while searching for #cacheDuring:. I think that it's not part of other Smalltalk dialects, never saw it used in Visualworks, Dolphin. A vast majority of us should agree that it does not qualify as idiomatic. IMO it does not add enough value to whileTrue. > |
> On 2020-03-30, at 2:23 PM, Nicolas Cellier <[hidden email]> wrote: > > idiomatic: using, containing, or denoting expressions that are natural to a native speaker. > So whileTrue: is natural for a native Smalltalker Exactly. And as a native speaker of Smalltalk I find doWhileTrue: unspeakably ugly. [this doThat ] doWhileTrue:[ thing farkle] I mean, just look at it. Which block is the one being tested for the boolean? Are we saying this doThat gets excuted while thing farkle returns true? Or while this doThat returns true we keep executing think farkle? [this doThat ] whileTrueDo:[ thing farkle] ... is at least bearable but seriously, why do we need anything other than whileTrue: here? tim -- tim Rowledge; [hidden email]; http://www.rowledge.org/tim Strange OpCodes: QVC: Question Valid Command |
> [this doThat ] doWhileTrue:[ thing farkle]
> > I mean, just look at it. Which block is the one being tested for the boolean? Are we saying this doThat gets excuted while thing farkle returns true? Or while this doThat returns true we keep executing think farkle? > > [this doThat ] whileTrueDo:[ thing farkle] > > ... is at least bearable but seriously, why do we need anything other than whileTrue: here? +1 Stef |
In reply to this post by timrowledge
+100
/—————————————————————/ For encrypted mail use [hidden email] - Free account at ProtonMail.com Web: https://objectnets.net and https://objectnets.org https://datascilv.com https://datascilv.org On Mar 30, 2020, at 15:39, tim Rowledge <[hidden email]> wrote:
|
In reply to this post by Christoph Thiede
Hi Christoph, On Mon, Mar 30, 2020 at 10:58 AM Thiede, Christoph <[hidden email]> wrote:
Ugh, horrible. The whileTrue is Smalltalk. doWhilerye: is some kind of attempt to do C. I have to say that I *hate* diWhileTrue:. whileTrue is beautifully elegant. You'll find it natural if you try and leave behind the damage from more conventional control-flow ischemes.
Two blocks where one will do? Unnecessary. Blocks are objects and understand messages, so whileTrue is coherent with the rest of the system, more concise, and indeed to my eyes much more elegant.
_,,,^..^,,,_ best, Eliot |
Hi all! Yes, #doWhileTrue: does not improve readability compared to #whileTrue and #whileTrue:. Either way, you have to understand that the last statement in a block is its returned value. I personally don't like it because "do" kind of means enumerating a collection. :-) And do-it! Ha! ;-) Let's follow that thought ... so, #doWhileTrue: becomes #do:whileTrue: #(1 2 3 4) do: [:ea | Transcript showln: ea] whileTrue: [:ea | ea < 3]. That is already possible with #select:, #reject:, or maybe #detect:: #(1 2 3 4) select: [:ea | ea < 3] thenDo: [:ea | Transcript showln: ea]. (#(1 2 3 4) select: [:ea | ea < 3]) do: [:ea | Transcript showln: ea]. #(1 2 3 4) detect: [:ea | Transcript showln: ea. ea >= 3] ifNone: []. ... Funny. And out of topic here. :-) There is no need for #doWhileTrue:. We should deprecate it. Best, Marcel
|
On Wed, Apr 1, 2020 at 12:07 AM Marcel Taeumel <[hidden email]> wrote:
+1
_,,,^..^,,,_ best, Eliot |
In reply to this post by marcel.taeumel
Every pet convenience method doesn’t need to be in the trunk.
+1 /—————————————————————/ For encrypted mail use [hidden email] - Free account at ProtonMail.com Web: https://objectnets.net and https://objectnets.org https://datascilv.com https://datascilv.org On Apr 1, 2020, at 00:07, Marcel Taeumel <[hidden email]> wrote:
|
In reply to this post by Levente Uzonyi
> 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:
(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 <[hidden email]> im Auftrag von Levente Uzonyi <[hidden email]>
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 <[hidden email]> im Auftrag von Nicolas Cellier <[hidden email]> > 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 <[hidden email]> 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 <[hidden email]> im Auftrag von [hidden email] <[hidden email]> > Gesendet: Montag, 30. März 2020 12:51 Uhr > An: [hidden email]; [hidden email] > 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.! > > > > >
Carpe Squeak!
|
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 <[hidden email]> im Auftrag von Levente Uzonyi <[hidden email]> > 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 <[hidden email]> im Auftrag von Nicolas Cellier <[hidden email]> > > 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 <[hidden email]> 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 <[hidden email]> im Auftrag von [hidden email] <[hidden email]> > > Gesendet: Montag, 30. März 2020 12:51 Uhr > > An: [hidden email]; [hidden email] > > 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.! > > > > > > > > > > > > |
Free forum by Nabble | Edit this page |