简体   繁体   中英

Perform an assignment and an operation using a ternary operator + && in Objective-C?

In the name of ternary bliss (and for a disdain of the verbose)... I am hoping, and am somewhat surprised that....

BOOL isItOpen = YES;
isItOpen = (isItOpen ? YES : NO); // yes, dumbie, it's open.

works fine… but that…

isItOpen = (isItOpen ? [it close] && NO : [it open] && YES);

results in Invalid operands to binary expression ('void' and 'int')

I can't seem to track down a simple yes or no as to whether one can conditionally chain operations with && (or || ), like one does in say, BASH or PHP. I tried various combinations of & and && arrangements, to no avail.. as I am a C idiot... but if this "way of doing it" is NOT possible, linguistically… is there another - that is as concise? (ie, no if s involed?)

The C (and by extension, C++ and Objective-C 1 ) operators form expressions ; they're designed to evaluate to a value, rather than control program flow.

So whilst ?: , && and || all offer short-circuit evaluation of their arguments, you can't use them to conditionally call arbitrary functions; 2 you should use traditional control-flow constructs (ie if ) for that.

You could use the little-known comma operator to achieve this, but I strongly recommend that you don't , because it's highly unidiomatic, and difficult to read. eg:

isItOpen = condition ? (func1(), NO) : (func2(), YES);


  1. Actually, I don't know Objective-C. For all know, it might be possible!
  2. And by "arbitrary", I mean functions that return void , or a type that's not implicitly convertible to bool in the case of && and || , or a non-matching type in the case of ?: .

Your code would work fine as long as the close and open methods you are executing on it return boolean values. Otherwise, no cigar.

If you want to use the ternary operator, you can do like this:

isItOpen ? ([it close], isItOpen = NO) : ([it open], isItOpen = YES);

Or:

isItOpen ? [it close] : [it open];
isItOpen = !isItOpen;

But this is not a good programming style and you should avoid it.

The following code is much more readable (at least by a C/C++/Objective-C programmer):

if (isItOpen)
    [it close];
else
    [it open];
isItOpen = !isItOpen;

In order of preference, I recommend you use the third version of the code, then the second, then the first.

The difference you are experiencing is due to Objective-C having:

(a) true procedures (void functions/methods) which return no value; and (b) a stronger type system than PHP

In your example the primary problem is (a) - you are calling methods which return nothing , and nothing is not a boolean value.

In PHP functions always return something , a function defined as returning void is actually defined as returning a "useless" value. However PHP will convert just about anything to anything (and does so inconsistently, for added "fun"), so a "useless" value has a boolean value - though what that is probably depends on the phase of the moon ;-) This feature does mean that you can reliably chain a "void" function after one which returns a value - <expr convertible to boolean> && <"void" function> will work in PHP (but the resulting boolean value is arbitrary). The same thing will not work in Objective-C (do not try to fix it with the comma operator, there are hidden traps with that operator).

So provided you stick with functions/methods which return either a boolean, or a type implicitly or explicitly convertible to boolean (eg for pointer types nil is false, other values true; for integral types 0 is false, everything else true) you can "conditionally chain" operations. Whether you should do this is a different question...

PS If you want to be confusing, this is short:

(isItOpen = !isItOpen) ? [it open] : [it close];

which will make most folks do a double-take ;-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM