Is there a difference between YES/NO,TRUE/FALSE and true/false in objective-c?

Objective CBoolean

Objective C Problem Overview


Simple question really; is there a difference between these values (and is there a difference between BOOL and bool)? A co-worker mentioned that they evaluate to different things in Objective-C, but when I looked at the typedefs in their respective .h files, YES/TRUE/true were all defined as 1 and NO/FALSE/false were all defined as 0. Is there really any difference?

Objective C Solutions


Solution 1 - Objective C

I believe there is a difference between bool and BOOL, check out this webpage for an explanation of why:
http://iosdevelopertips.com/objective-c/of-bool-and-yes.html

Because BOOL is an unsigned char rather than a primitive type, variables of type BOOL can contain values other than YES and NO.

Consider this code:

BOOL b = 42;

if (b) {
    printf("b is not NO!\n");
}

if (b != YES) {
    printf("b is not YES!\n");
}

The output is:

> b is not NO!
> b is not YES!

For most people this is an unnecessary concern, but if you really want a boolean it is better to use a bool. I should add: the iOS SDK generally uses BOOL on its interface definitions, so that is an argument to stick with BOOL.

Solution 2 - Objective C

There is no practical difference provided you use BOOL variables as booleans. C processes boolean expressions based on whether they evaluate to 0 or not 0. So:

if(someVar ) { ... }
if(!someVar) { ... }

means the same as

if(someVar!=0) { ... }
if(someVar==0) { ... }

which is why you can evaluate any primitive type or expression as a boolean test (including, e.g. pointers). Note that you should do the former, not the latter.

Note that there is a difference if you assign obtuse values to a so-called BOOL variable and test for specific values, so always use them as booleans and only assign them from their #define values.

Importantly, never test booleans using a character comparison -- it's not only risky because someVar could be assigned a non-zero value which is not YES, but, in my opinion more importantly, it fails to express the intent correctly:

if(someVar==YES) { ... } // don't do this!
if(someVar==NO ) { ... } // don't do this either!

In other words, use constructs as they are intended and documented to be used and you'll spare yourself from a world of hurt in C.

Solution 3 - Objective C

I did an exhaustive test on this. My results should speak for themselves:

//These will all print "1"
NSLog(@"%d", true == true);
NSLog(@"%d", TRUE == true);
NSLog(@"%d", YES  == true);
NSLog(@"%d", true == TRUE);
NSLog(@"%d", TRUE == TRUE);
NSLog(@"%d", YES  == TRUE);
NSLog(@"%d", true == YES);
NSLog(@"%d", TRUE == YES);
NSLog(@"%d", YES  == YES);

NSLog(@"%d", false == false);
NSLog(@"%d", FALSE == false);
NSLog(@"%d", NO    == false);
NSLog(@"%d", false == FALSE);
NSLog(@"%d", FALSE == FALSE);
NSLog(@"%d", NO    == FALSE);
NSLog(@"%d", false == NO);
NSLog(@"%d", FALSE == NO);
NSLog(@"%d", NO    == NO);


//These will all print "0"
NSLog(@"%d", false == true);
NSLog(@"%d", FALSE == true);
NSLog(@"%d", NO    == true);
NSLog(@"%d", false == TRUE);
NSLog(@"%d", FALSE == TRUE);
NSLog(@"%d", NO    == TRUE);
NSLog(@"%d", false == YES);
NSLog(@"%d", FALSE == YES);
NSLog(@"%d", NO    == YES);

NSLog(@"%d", true == false);
NSLog(@"%d", TRUE == false);
NSLog(@"%d", YES  == false);
NSLog(@"%d", true == FALSE);
NSLog(@"%d", TRUE == FALSE);
NSLog(@"%d", YES  == FALSE);
NSLog(@"%d", true == NO);
NSLog(@"%d", TRUE == NO);
NSLog(@"%d", YES  == NO);

The output is:

2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.072 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.076 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.082 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.091 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.092 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.097 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.098 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.101 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0

Solution 4 - Objective C

You might want to read the answers to this question. In summary, in Objective-C (from the definition in objc.h):

typedef signed char        BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.
#define OBJC_BOOL_DEFINED


#define YES             (BOOL)1
#define NO              (BOOL)0

Solution 5 - Objective C

The main (dangerous!) difference between true and YESis in JSON serialization.

For example, we have JSON-type server request and need to send true/false in json sence:

NSDictionary *r1 = @{@"bool" : @(true)};
NSDictionary *r2 = @{@"bool" : @(YES)};
NSDictionary *r3 = @{@"bool" : @((BOOL)true)};

Then we convert it to JSON string before sending as

NSData *data = [NSJSONSerialization  dataWithJSONObject:requestParams options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

The result is

jsonString1 // {"bool":1}
jsonString2 // {"bool":true}
jsonString3 // {"bool":true}

Due to API logic jsonString1 could result in an error.

So be careful with booleans in Objective-C.

To sum up, only exact @YES and casted value as @((BOOL)expression) are of __NSCFBoolean type and converted to true with JSON serialization. Any other expressions like @(expression1 && expression2) (even @(YES && YES)) are of __NSCFNumber (int) type and converted to 1 in JSON.

P.S. You can simply use string-valued boolean

@{@"bool" : @"true"}; // in JSON {"bool":true}

Solution 6 - Objective C

There is a subtle bug that no one has mentioned here, that I thought I would include... more of a logical error than anything:

int i = 2;
if(i);        //true
if(i==YES);   // false
if((!!i)==YES); //true

so the issue here is just that (YES==1) and in C the comparison isn't a boolean one, but one based on value.

because YES is just a #define (rather than something intrinsic to the language), it has to be some value, and 1 makes the most sense.

Solution 7 - Objective C

I think they add YES/NO to be more self-explanatory in many cases. For example:

[button setHidden:YES];

sounds better than

[button setHidden:TRUE];

Solution 8 - Objective C

First let's examine what true and false is and what gives them meaning in the first place.

we can construct a structure called if a then b else c in lambda calculus as follows:

(\ifThenElse. <use if then else>)(\a. \b. \c. a b c)

In JavaScript, This looks like this:

(function(ifThenElse) {
    // use ifThenElse
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
});

in order for ifThenElse to be useful, we need a function "true" that chooses either right or left, and does that while ignoring the other option, or a function "false" that chooses the option "true" doesn't take.

We can define these functions as follows:

(\true. <use true>)(\a. \b. a) and (\false. <use false>)(\a. \b. b)

in JavaScript it looks like this:

(function(True) {
    // use True
})(function(a) {
     return function(b) {
         return a;
     }
});

(function(False) {
    // use True
})(function(a) {
     return function(b) {
         return b;
     }
});

now we can do the following

(\true. \false. \ifThenElse. \doThis. \doThat. ifThenElse true doThis doThat)
(\a. \b. a)(\a. \b. b)(\a. \b. \c. a b c)(\a. ())(\a. ())

with doThis and doThat being (\a. ()) because lambda calculus does not offer any services such as printing/math/strings, all we can do is do nothing and say we did it(and later cheat by replacing it with services in our system that provide side effects we want)

so let's see this in action.

(function(True) {
    return (function(False) {
        return (function(ifThenElse) {
            return (function(doThis) {
                return (function(doThat) {
                    return ifThenElse(True)(doThis)(doThat);
                });
            });
        });
    })
})(function(a) {
     return function(b) {
         return a;
     }
})(function(a) {
     return function(b) {
         return b;
     }
})(function(a) {
    return function(b) {
        return function(c) {
            return a(b)(c);
        };
    };
})(function(a) { console.log("you chose LEFT!"); })
(function(a) {console.log("you chose RIGHT");})();

That's a deep environment that could be simplified if we were allowed to use arrays/maps/arguments/or more than one statement to split into multiple functions, but i want to keep is as pure as I can limiting myself to functions of exactly one argument only.

notice that the name True/False has no inherent significance, we can easily rename them to yes/no, left/right, right/left, zero/one, apple/orange. It has significance in that whatever choice is made, it is only caused by the kind of chooser made it. So if "LEFT" is printed, we know that the chooser could only be true, and based on this knowledge we can guide our further decisions.

So to summarize

function ChooseRight(left) {
    return function _ChooseRight_inner(right) {
        return right;
    }
}
function ChooseLeft(left) {
    return function _ChooseLeft_inner(right) {
        return left;
    }
}

var env = {
    '0': ChooseLeft,
    '1': ChooseRight,
    'false': ChooseRight,
    'true': ChooseLeft,
    'no': ChooseRight
    'yes': ChooseLeft,
    'snd': ChooseRight,
    'fst': ChooseLeft
};
var _0 = env['0'];
var _1 = env['1'];
var _true = env['true'];
var _false = env['false'];
var yes = env['yes'];
var no = env['no'];

// encodes church zero or one to boolean
function lambda_encodeBoolean(self) {
    return self(false)(true);
}
// decodes a Boolean to church zero or one
function lambda_decodeBoolean(self) {
    console.log(self, self ? env['true'] : env['false']);
    return self ? env['true'] : env['false'];
}

lambda_decodeBoolean('one' === 'two')(function() {
    console.log('one is two');
})(function() {
    console.log('one is not two');
})();

lambda_decodeBoolean('one' === 'one')(function() {
    console.log('one is one');
})(function() {
    console.log('one is not one');
})();

Solution 9 - Objective C

No, YES/NO is a different way to refer to TRUE/FALSE(1/0)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKevlarView Question on Stackoverflow
Solution 1 - Objective CDan JView Answer on Stackoverflow
Solution 2 - Objective CLawrence DolView Answer on Stackoverflow
Solution 3 - Objective CKy.View Answer on Stackoverflow
Solution 4 - Objective CBarry WarkView Answer on Stackoverflow
Solution 5 - Objective CmalexView Answer on Stackoverflow
Solution 6 - Objective CGrady PlayerView Answer on Stackoverflow
Solution 7 - Objective CMarcoView Answer on Stackoverflow
Solution 8 - Objective CDmitryView Answer on Stackoverflow
Solution 9 - Objective CMarcoView Answer on Stackoverflow