PDA

View Full Version : Question about BOOL and style? Kochan 2.0 page 198




mdeh
Jan 18, 2009, 10:33 AM
if ([Square isSubclassOfClass: [Rectangle class]] == YES);


In the definition of "isSubclassOfClass" the return type is BOOL. BOOL is defined as a signed char.
Now, if NO is 0, and YES **could** be anything but 0, would it not be better??? to have the comparison be to "!= 0" ?
Thanks in advance.



MrFusion
Jan 18, 2009, 10:43 AM
if ([Square isSubclassOfClass: [Rectangle class]] == YES);


In the definition of "isSubclassOfClass" the return type is BOOL. BOOL is defined as a signed char.
Now, if NO is 0, and YES **could** be anything but 0, would it not be better??? to have the comparison be to "!= 0" ?
Thanks in advance.

You don't even have to bother with the comparison.

BOOL succes = YES or NO;
If (succes)
dosomething when yes
else
sosomethingelse when no

If (!succes)
dosomething when no
else
sosomethingelse when yes

If ([afunction returnsBOOL])
dosomething when yes
else
sosomethingelse when no

MacDonaldsd
Jan 18, 2009, 12:22 PM
if ([Square isSubclassOfClass: [Rectangle class]] == YES);


In the definition of "isSubclassOfClass" the return type is BOOL. BOOL is defined as a signed char.
Now, if NO is 0, and YES **could** be anything but 0, would it not be better??? to have the comparison be to "!= 0" ?
Thanks in advance.

The issue is readability and having YES or NO improves this. And like MrFusion says you don't have to always type == NO etc.

skochan
Jan 18, 2009, 02:57 PM
The issue is readability and having YES or NO improves this. And like MrFusion says you don't have to always type == NO etc.

Yes, it is a readability issue, but there's a little more to it than that. You should be aware that YES is defined in a system header file as 1. So if you write a method that returns a BOOL value, and you return a nonzero value to indicate "yes" or "true", then an expression such as

if ( [myObject myMethod] == YES )

will not work unless the method just happens to return 1.

That means if you write a BOOL method, you should return YES for true and NO for false so that expressions such as the one shown will work. On the flip side, if you're invoking a method you didn't write, it's safer, though less readable, to test for truth without the explicit comparison to YES. That's in case the coder of the BOOL method returns a nonzero value for true. It's a little bit of a mess, as you can see. The documentation for the BOOL method should indicate the values the method returns, and that can serve as your guide.


Cheers,

Steve Kochan

lee1210
Jan 18, 2009, 04:31 PM
Not that my opinion is more valid than anyone else posting, but i thought i'd add it on this one. The failure of C to include a boolean type, and force only that type to be used in a conditional is a serious flaw. It's not the end of the world, people obviously get by without it, but it can lead to some real sloppiness and some serious errors.

The BOOL typedef that's used in Objective-C is nice, TRUE and FALSE are #defined to 0 and 1 on a lot of systems as well. This sort of helps with readability, but doesn't address the real problem.

For example:
if(x = y) {
...
}

This will be true as long as y is non-zero. In general, the intent is to use == to evaluate equivalence, not = for assignment, but an assignment expression evaluates to its second operand so you can do things like:
x = y = z = 3;

It also leads to people using if statements to check for nullity since a null pointer is equal to 0, etc. This seems pretty sloppy to me, because in english you want to ask "Is this pointer (non-)null?" not "Is this pointer?". While computer science has strong ties to logic and philosophy, the latter doesn't really make sense in this context. For this reason i would prefer that a logical operator be used in cases like this, so you say:
if(myPtr != null) {
...
}
or
if(myPtr != nil) {
...
}
so what you're checking for is explicit.

In this magical world where C supports a real boolean that must be used in an if statement, if you had a function that returned a boolean type, it would be perfectly correct (and readable, in my opinion if the function was named nicely) to just check its return value. In this imperfect world of typedef'd BOOLs, usw. we're stuck with the debate at hand, and some very difficult to read code out there.

One workaround for the issue Steve mentioned (possibility of an external function that returns a BOOL not returning 1/YES for "truth") would be to only check against NO. This would either require you to always switch the if and else portion of your control structure, or check if things are != to NO instead of == to YES. It's ugly, but it would be "safer" than just using == YES for the reasons Steve mentioned.

This doesn't really lead anywhere, but I thought i'd chime in because of some of the horrors i've come across (and assuredly I've written) that depend on this strange behavior. I understand on a lot of microarchitectures there's a JNE or JEQ sort of instruction that only checks against 0, which makes mapping easy... but a little more work in this area originally would have gone a long way in my opinion.

-Lee

mdeh
Jan 18, 2009, 08:52 PM
The failure of C to include a boolean type, and force only that type to be used in a conditional is a serious flaw.-Lee

Could you elaborate slightly on this. Are you saying there is **NO** boolean type in C. If that is true, I do not follow the second part of the sentence.



The BOOL typedef that's used in Objective-C is nice, TRUE and FALSE are #defined to 0 and 1 on a lot of systems as well. This sort of helps with readability, but doesn't address the real problem. -Lee

I **thought** that in plain old C, the value ZERO represented FALSE, and anything but ZERO represents True. Then in Obj-C, there seem to be 2 boolean values, _Bool and BOOL. Other than the definitions of YES and NO being 1 and 0 things get fuzzy!!! Perhaps, if you are so inclined, you or Steve might be able to put this all in perspective.

skochan
Jan 18, 2009, 09:36 PM
Could you elaborate slightly on this. Are you saying there is **NO** boolean type in C. If that is true, I do not follow the second part of the sentence.

There is a boolean type in C. However, it was added to the language a little late in the game (as part of what's known as the ANSI C99 standard). The type is _Bool, and it is a built-in data type. Only the values true and false can be assigned to a _Bool variable.

On the other hand, BOOL is not a built-in type, it's a typedef defined in a system header file. It was added to the Objective-C language before the _Bool type existed in C. You can assign any value to a BOOL variable; however, the convention is to assign it just the values YES or NO (which are macros defined in a system header file).

Because of this history (and the fact that it took a while for ANSI C 99 compilers to be developed), boolean methods in the frameworks have been declared to return BOOL values and not _Bool values.

Hope this helps.

Cheers,

Steve Kochan

lee1210
Jan 18, 2009, 09:40 PM
Could you elaborate slightly on this. Are you saying there is **NO** boolean type in C. If that is true, I do not follow the second part of the sentence.

There is(well, was originally) no boolean type in C. What i meant was that it would be great if there WAS a boolean type originally, and an expression that evaluates to that type were the ONLY thing that you could put in an if, the condition of a for, etc. I realize the ambiguity now. My intention was "The failure of C to include a boolean type which would be the only type that could be used in a conditional...". Hopefully that's clearer. Blasted english.



I **thought** that in plain old C, the value ZERO represented FALSE, and anything but ZERO represents True. Then in Obj-C, there seem to be 2 boolean values, _Bool and BOOL. Other than the definitions of YES and NO being 1 and 0 things get fuzzy!!! Perhaps, if you are so inclined, you or Steve might be able to put this all in perspective.

Right, 0 is a negative condition, any non-zero value is a positive condition when evaluated in a conditional. Any sort of bool, boolean. BOOL, _bool, _booly, _mybool, etc.(except _Bool) in C is going to be typedef'd to something else. In Objective-C, it's in objc.h:

typedef signed char BOOL;
#define YES (BOOL)1
#define NO (BOOL)0
#define nil 0 /* id of Nil instance */


I included a few other items of interest in that header file. What this all adds up to is a (respectable) effort to make a boolean/logical kind of thing that is usable in place of something built-in in the language. The real issue is "responsible use" of what is available. It's easier to write ugly C than pretty C, but with some extra work it's doable, and people that have to maintain your code won't hate you. This pretty much all applies to Objective-C, too, since it has such inexorable ties to C, being that all C is Objective-C.

-Lee

EDIT: You and Steve mentioned the _Bool type. Unfortunately C99 is not widely used, even if compilers' support for it is improving. Even with this available you don't HAVE to use something that evaluates to _Bool as your condition in a conditional, and programers don't need to use it.

EDIT 2: also, listen to Steve. He's the published author, I'm just a guy on the Internet. =)

ChrisA
Jan 18, 2009, 10:46 PM
if ([Square isSubclassOfClass: [Rectangle class]] == YES);

Actually the "== YES" part is borderline wrong What you have written is code that one day might not work if the funtion returned (say) 12 rather than one. It is perfectly OK to return 12 is "true" but your comparison would not longer work as written.

One more thing. When ever you do have an == be sure and lplace the constant on the left side. This makes it clear it is NOT an asignment and also fails to compile if you leave off one of the two equal signs, a common error.

I don't know how many times I've typo'd and writen "if(foobar=2)..." Man that is hard to find because it looks write. But 2=foobar would not compile.

In the end it is best to say either "if( foobar )..." or "if( !foobar )" This is much more clear and work even if foobar() returns 12 to indicate true.

skochan
Jan 18, 2009, 11:19 PM
Actually the "== YES" part is borderline wrong What you have written is code that one day might not work if the funtion returned (say) 12 rather than one. It is perfectly OK to return 12 is "true" but your comparison would not longer work as written.

In the end it is best to say either "if( foobar )..." or "if( !foobar )" This is much more clear and work even if foobar() returns 12 to indicate true.

Well, this is not a black and white issue, but I don't agree with you. :). As I stated, if a method is defined to return a value of type BOOL, then it must return a value of either YES or NO; otherwise it has not been properly coded. The unfortunate part is that programmers may not adhere to that convention. As I mentioned at the end of my previous post, the documentation for the method should describe the values returned (e.g. returns YES if the strings match, NO if they do not). And you can be sure that any BOOL methods in Apple's frameworks will return either YES or NO.

For example. from Apple's NSFileManager documentation:


- (BOOL)isWritableFileAtPath: (NSString *) path

Parameters

path

A file path.

Return Value

YES if the invoking object appears able to write to the file specified in path, otherwise NO. If the file at path does not exist, this method returns NO.

...


By the way, to all who participated here, great discussion! And Lee1210, don't sell yourself short. Your opinion is certainly just as valid as mine and provoked an excellent discussion.

Cheers,

Steve Kochan

Sander
Jan 19, 2009, 10:39 AM
It also leads to people using if statements to check for nullity since a null pointer is equal to 0, etc. This seems pretty sloppy to me, because in english you want to ask "Is this pointer (non-)null?" not "Is this pointer?". While computer science has strong ties to logic and philosophy, the latter doesn't really make sense in this context.

It depends on what you think the "if" statement does. If you try to post-instill boolean awareness into C, you'd say something like "the if-statement executes the following block or statement if its argument evaluates to 'true'."

But there is no notion of "true" in C, just like you said. So if you teach people that the if-statement "executes the following block or statement if its argument evaluates to nonzero", there is no problem at all. It is widely accepted C idiom to test for non-nillness of a pointer by doing "if (pointer) ...", and the confusion only arises when you think there's any boolean logic involved...

Just the opinion of another published author, albeit less so than Steve :-)