What is a young Smalltalker to do? SmallLint forcefully suggests that:
^ Preferences optionalButtons ifTrue: [OBFixedButtonPanel new] should be rewritten as: ^ Preferences optionalButtons ifTrue: [OBFixedButtonPanel new] ifFalse: [nil] which would be fine, but as soon as I try and pretty print the rejigged method, it reverts to the version without the ifFalse: clause? Two tools enter, one tool leaves. But which one? |
On Tue, 26 Jun 2007 13:24:39 -0700, Piers Cawley <[hidden email]>
wrote: > What is a young Smalltalker to do? SmallLint forcefully suggests that: > > ^ Preferences optionalButtons > ifTrue: [OBFixedButtonPanel new] > > should be rewritten as: > > ^ Preferences optionalButtons > ifTrue: [OBFixedButtonPanel new] > ifFalse: [nil] > > which would be fine, but as soon as I try and pretty print the > rejigged method, it reverts to the version without the ifFalse: > clause? The latter strikes me as silly. In a language where "if" is part of the grammar, I can see it sort-of making sense, especially if nesting "if"s, to include "else"s with NOPs. |
On Tue, 26 Jun 2007 13:45:22 -0700, Blake <[hidden email]> wrote:
> The latter strikes me as silly. In a language where "if" is part of the > grammar, I can see it sort-of making sense, especially if nesting "if"s, > to include "else"s with NOPs. The issue is, what does the expression return, in the false case, if #ifFalse: isn't there? It may be a Smalltalk standard to return nil in that case - I have no idea. Personally, when I'm doing something with an expression (like returning it, or assigning it), I always make it very explicit what I (the programmer) expect to happen in all cases... Later, Jon -------------------------------------------------------------- Jon Hylands [hidden email] http://www.huv.com/jon Project: Micro Raptor (Small Biped Velociraptor Robot) http://www.huv.com/blog |
On Tue, 26 Jun 2007 14:00:36 -0700, Jon Hylands <[hidden email]> wrote:
> On Tue, 26 Jun 2007 13:45:22 -0700, Blake <[hidden email]> wrote: > >> The latter strikes me as silly. In a language where "if" is part of the >> grammar, I can see it sort-of making sense, especially if nesting "if"s, >> to include "else"s with NOPs. > > The issue is, what does the expression return, in the false case, if > #ifFalse: isn't there? > > It may be a Smalltalk standard to return nil in that case - I have no > idea. Personally, when I'm doing something with an expression (like > returning it, or assigning it), I always make it very explicit what I > (the programmer) > expect to happen in all cases... Good point. I didn't note the ^ at the beginning and was just looking at the statment. However, is the question not really "What do the booleans return from an if* statement if the conditional is not met"? In which case, the answer is "nil". Which, perhaps inevitably, leads me back to my original conclusion: It's silly. "if" is not a language construct with undefined and potentially ambiguous results. It's a set of messages sent to a class. It's kind of like all those languages that use "for" loops in which the control variable is undefined after the loop. Lint tools will warn you about using that control variable; that would just be silly in Smalltalk. I guess if we're talking portability though, it might be a valid question. I'm not sure the Smalltalk spec mandates that instances of True and False must return nil. But what else =would= they return? Self? ===Blake=== |
On Jun 26, 2007, at 23:59 , Blake wrote:
> However, is the question not really "What do the booleans return > from an if* statement if the conditional is not met"? In which > case, the answer is "nil". > > I guess if we're talking portability though, it might be a valid > question. I'm not sure the Smalltalk spec mandates that instances > of True and False must return nil. "ifTrue: aBlock" is short-hand for "ifTrue: trueBlock ifFalse: []". The value of an empty block is nil by definition. That's why True and False must return nil in #ifFalse: and #ifTrue:, respectively. - Bert - |
Bert Freudenberg wrote:
>> I guess if we're talking portability though, it might be a valid >> question. I'm not sure the Smalltalk spec mandates that instances of >> True and False must return nil. > > "ifTrue: aBlock" is short-hand for "ifTrue: trueBlock ifFalse: []". The > value of an empty block is nil by definition. That's why True and False > must return nil in #ifFalse: and #ifTrue:, respectively. That is not necessarily the case. One can make an equally good argument saying that "foo ifTrue:[...]" should expand to "foo ifTrue:[...] ifFalse:[foo]" which is coincidentally true for ifNil:ifNotNil: and *should* be true (and I'm glad we fixed this in Croquet) for ifEmpty:ifNotEmpty:. In other words if it is the case that: 42 ifNil:[...] => 42 #(1 2 3) ifEmpty:[...] => #(1 2 3) then it seems quite consistent to have false ifTrue:[...] => false. (not that I'm proposing to change this btw, since it would break a whole bunch of stuff but it's perfectly consistent with other semantics that are generally deemed "intuitive") Cheers, - Andreas |
In reply to this post by Bert Freudenberg
On Tue, 26 Jun 2007 23:54:39 -0700, Bert Freudenberg
<[hidden email]> wrote: > "ifTrue: aBlock" is short-hand for "ifTrue: trueBlock ifFalse: []". The > value of an empty block is nil by definition. That's why True and False > must return nil in #ifFalse: and #ifTrue:, respectively. So, lint is in this case un-short-handing. |
In reply to this post by Andreas.Raab
On Jun 27, 2007, at 9:02 , Andreas Raab wrote: > Bert Freudenberg wrote: >>> I guess if we're talking portability though, it might be a valid >>> question. I'm not sure the Smalltalk spec mandates that instances >>> of True and False must return nil. >> "ifTrue: aBlock" is short-hand for "ifTrue: trueBlock ifFalse: >> []". The value of an empty block is nil by definition. That's why >> True and False must return nil in #ifFalse: and #ifTrue:, >> respectively. > > That is not necessarily the case. One can make an equally good > argument saying that "foo ifTrue:[...]" should expand to "foo > ifTrue:[...] ifFalse:[foo]" which is coincidentally true for > ifNil:ifNotNil: and *should* be true (and I'm glad we fixed this in > Croquet) for ifEmpty:ifNotEmpty:. In other words if it is the case > that: > > 42 ifNil:[...] => 42 > #(1 2 3) ifEmpty:[...] => #(1 2 3) > > then it seems quite consistent to have > > false ifTrue:[...] => false. > > (not that I'm proposing to change this btw, since it would break a > whole bunch of stuff but it's perfectly consistent with other > semantics that are generally deemed "intuitive") Granted. I understood the question to be about wether the behavior was arbitrary and Squeak-specific or actually specified and portable. I'd argue it's the latter, if only because ifTrue:/ifFalse: predates the other constructs by a large margin and all Smalltalk variants inherited that behavior. - Bert - |
In reply to this post by Andreas.Raab
On Wed, 27 Jun 2007 00:02:46 -0700, Andreas Raab <[hidden email]>
wrote: > ifEmpty:ifNotEmpty:. In other words if it is the case that: > > 42 ifNil:[...] => 42 > #(1 2 3) ifEmpty:[...] => #(1 2 3) > > then it seems quite consistent to have > > false ifTrue:[...] => false. > > (not that I'm proposing to change this btw, since it would break a whole > bunch of stuff but it's perfectly consistent with other semantics that > are generally deemed "intuitive") Given that we're off in alternate realities, this probably isn't that important but wouldn't the above require a lot of code like this to be written: ^someTest ifTrue:[someObject] ifFalse: [nil]. because otherwise the return value will be a valid non-nil object that must be tested for. In other words, unless you set the result to nil specifically, clients of the code must be prepared to handle a valid object, nil (as now), and a boolean. And they must have awareness of the fact that sometimes True means nil and sometimes False means nil (or I guess that a boolean means nil). And then what if the non-nil block returns a boolean? Not that such would be insurmountable, but it seems like the approach as implemented is cleaner. ===Blake=== |
In reply to this post by Blake-5
On Jun 27, 2007, at 9:14 , Blake wrote: > On Tue, 26 Jun 2007 23:54:39 -0700, Bert Freudenberg > <[hidden email]> wrote: > >> "ifTrue: aBlock" is short-hand for "ifTrue: trueBlock ifFalse: >> []". The value of an empty block is nil by definition. That's why >> True and False must return nil in #ifFalse: and #ifTrue:, >> respectively. > > So, lint is in this case un-short-handing. Right. As Andreas points out it is conceivable that some Smalltalk would redefine the meaning so this would be more portable, and it might be considered more readable because it spells out the other case explicitly, leaving no one to wonder about the return value. - Bert - |
In reply to this post by Blake-5
On Wed, 27 Jun 2007 00:26:55 -0700, Blake <[hidden email]> wrote:
> > Given that we're off in alternate realities, this probably isn't that > important but wouldn't the above require a lot of code like this to be > written: > > ^someTest ifTrue:[someObject] ifFalse: [nil]. Which, I guess, now that Bert re-points it out, is exactly where we started. Heh. |
In reply to this post by Andreas.Raab
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 Andreas Raab schrieb: > That is not necessarily the case. One can make an equally good argument > saying that "foo ifTrue:[...]" should expand to "foo ifTrue:[...] > ifFalse:[foo]" which is coincidentally true for ifNil:ifNotNil: and > *should* be true (and I'm glad we fixed this in Croquet) for > ifEmpty:ifNotEmpty:. In other words if it is the case that: > > 42 ifNil:[...] => 42 > #(1 2 3) ifEmpty:[...] => #(1 2 3) I had above expectation for ifEmpty: once and got so badly burned, that I chickened out of using ifNil:, ifEmtpy: and their homies completely. Alex -----BEGIN PGP SIGNATURE----- Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGgjkhYiF2wSTEZ9gRAiK6AKD12y8htqds/V80+rQmNUKFoRtbwACfdE3K GLrgsovXUVA2/PKaG8tlHZI= =2lRB -----END PGP SIGNATURE----- |
In reply to this post by Andreas.Raab
Hi andreas
> That is not necessarily the case. One can make an equally good > argument saying that "foo ifTrue:[...]" should expand to "foo > ifTrue:[...] ifFalse:[foo]" which is coincidentally true for > ifNil:ifNotNil: and *should* be true (and I'm glad we fixed this in > Croquet) for ifEmpty:ifNotEmpty:. In other words if it is the case > that: > > 42 ifNil:[...] => 42 > #(1 2 3) ifEmpty:[...] => #(1 2 3) > Can you elaborate more on why it should be true for ifEmpty:? > then it seems quite consistent to have > > false ifTrue:[...] => false. > > (not that I'm proposing to change this btw, since it would break a > whole bunch of stuff but it's perfectly consistent with other > semantics that are generally deemed "intuitive") > > Cheers, > - Andreas > > |
In reply to this post by Bert Freudenberg
>On Jun 27, 2007, at 9:14 , Blake wrote:
> >>On Tue, 26 Jun 2007 23:54:39 -0700, Bert Freudenberg <[hidden email]> wrote: >> >>>"ifTrue: aBlock" is short-hand for "ifTrue: trueBlock ifFalse: []". The value of an empty block is nil by definition. That's why True and False must return nil in #ifFalse: and #ifTrue:, respectively. >> >>So, lint is in this case un-short-handing. > >Right. As Andreas points out it is conceivable that some Smalltalk would redefine the meaning so this would be more portable, and it might be considered more readable because it spells out the other case explicitly, leaving no one to wonder about the return value. I may be the one responsible for the shorthand here (but memory does not serve in this case). In any event, I'll add that I agree with the lint point of view that any of these paired expressions should include the nil branch when evaluated for value (as in assignments, as arguments, and as return values). The decompiler can recognize these cases, so I'd certainly agree with modifying the decompiler accordingly. When only evaluated for effect, the shorthand is not only simpler, but it invariably matches the program as originally written, so that should be retained. - Dan |
In reply to this post by Piers Cawley
Someone wrote a package where you could allow specific "violations"
for specific methods declared (I think) on the class side so that Lint would then ignore it going foward. I can't remember who did it, but it was in the last few years. You'd have to search the archives to find it.. On 6/26/07, Piers Cawley <[hidden email]> wrote: > What is a young Smalltalker to do? SmallLint forcefully suggests that: > > ^ Preferences optionalButtons > ifTrue: [OBFixedButtonPanel new] > > should be rewritten as: > > ^ Preferences optionalButtons > ifTrue: [OBFixedButtonPanel new] > ifFalse: [nil] > > which would be fine, but as soon as I try and pretty print the > rejigged method, it reverts to the version without the ifFalse: > clause? > > Two tools enter, one tool leaves. But which one? > > |
Free forum by Nabble | Edit this page |