[squeak-dev] ifTrue: vs. ifFalse:

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Tue Oct 18 19:20:15 UTC 2011

2011/10/18 Eliot Miranda <eliot.miranda at gmail.com>:
> On Tue, Oct 18, 2011 at 1:58 AM, Bert Freudenberg <bert at freudenbergs.de>
> wrote:
>> On 18.10.2011, at 05:11, Chris Muller wrote:
>> > (From vm-dev list)
>> >> But I much prefer foo ~~ bar ifTrue: than foo == bar ifFalse:.
>> >
>> > Hi Eliot.  May I ask why you prefer the former over the latter?
>> >
>> > I'm interested because I'm working on an application where the folks
>> > involved prefer something similar, to where they write (expr) not
>> > ifTrue: [ ] rather than (expr) ifFalse: [ ].
>> >
>> > I know you wouldn't do that but your statement definitely piqued my
>> > surprise and curiosity.
>> Maybe this is a clue: very few other programming languages have an
>> "else"-case without a preceding "if true". So maybe for people versed in
>> multiple languages the ifFalse: feels wrong?
> For me, it's not about feeling right or wrong, it's about directly
> expressing intent. For example, in some loop where a predicate is being used
> to select or reject elements I would write "obj predicate ifTrue:" if I were
> looking for the element based on predicate and "obj predicate ifFalse:" if I
> were trying to filter-out elements based on predicate, just as I'd write
> collection select: [:e| e predicate] to select items based on predicate
> and collection reject: [:e| e predicate] to filter them out, and I would
> /not/ write collection select: [:e| e predicate not] to filter them out
> unless performance was really really important (since reject: adds another
> block activation for each element).  I'm trying to communicate whether I'm
> selecting or rejecting based on predicate, and not wanting the reader to go
> through mental hoops by internally collapsing predicate not ifFalse: to
> predicate ifTrue: and vice verse.
>> I personally like "expr ifFalse:" better than "expr not ifTrue:".
> Agreed.  expr not ifTrue: & expr not ifFalse are perverse.

Well guys, while I agree, I just browsed senders of not and that's
1175 senders to refactor :)
Well, maybe NOT all the senders (hey how you translate this, (senders
allSatisfy: [:e | e shouldBeRefactored]) not or: [(senders anySatisfy:
[:e | e shouldBeRefactored not]) or: [(senders noneSatisfy: [:e | e
shouldBeRefactored not ]) not]]
I tend to slightly dislike the last triple negation ;)

Among the senders some answer true to your filter predicate, like
select: predicate not / anyStatisfy: predicate not / but others are
composed logic...
Some like

checkName: aFileName fixErrors: fixing
	hasBadChars := fName ~= correctedName.
	(hasBadChars and:[fixing not]) ifTrue:[^self error:'Invalid file name'].
	hasBadChars ifFalse:[^ fName].
	^ correctedName

shall easily become

	fname = correctedName ifTrue: [^fname].
	fixing ifTrue: [^correctedName].
	^self error: 'Invalid file name'

Some are tougher and would probably deserve a new selector like

	(self isPointers or: [ self isWords not ]) ifTrue: [ ^self ].

See https://code.google.com/p/pharo/issues/detail?id=2230 to just
measure how badly we tend to misunderstand negation and what mistakes
we make (same as subtraction is lot harder to learn than addition)


>> And I read "~~" as "not identical" which also has a mental "not" in it, so
>> I prefer "== ifFalse" :)
> Ah, there we differ.  I view == and ~~ as complementary predicates.  If I'm
> writing foo == bar ifTrue: I'm clearly selecting, and foo ~~ bar ifTrue: I'm
> clearly rejecting, but foo == bar ifFalse: is IMO worse (more cognitively
> demanding) than foo ~~ bar ifTrue:.

same for noneSatisfy: , notNil etc...

>> - Bert -
> --
> best,
> Eliot

More information about the Squeak-dev mailing list