Ternary assignment (memoization) operator in Objective-C
| Originator: | rix.rob | ||
| Number: | rdar://11825208 | Date Originated: | 07-Jul-2012 12:59 PM |
| Status: | Open | Resolved: | N/A |
| Product: | Developer Tools | Product Version: | Objective-C |
| Classification: | Enhancement | Reproducible: | Always |
I would like a memoization operator in clang for C, Objective-C, and possibly C++ if it wouldn’t conflict (I’m no expert, I leave that to you).
We have a ternary operator which lets us do conditional expressions:
foo? bar : quux
The result of this expression is bar if foo evaluates to true, and quux otherwise. Further, it short-circuits, meaning that only one of bar or quux are evaluated; if they have side-effects or are expensive to calculate, this can avoid pitfalls.
In addition, there’s a shorthand available (I believe as a GNU99 extension which clang supports, but I could be wrong about its provenance) for cases when the condition and positive result are the same expression:
foo ?: bar
This has two interesting facets:
1. It’s more or less equivalent to foo ? foo : bar, except that it doesn’t evaluate foo twice, meaning it can in some cases be faster and avoid errors involving duplicate side-effects triggered by evaluating foo.
2. It works particularly well for object pointers as a way of saying “foo, if possible, defaulting to bar.” In this usage it is directly comparable to Ruby and JavaScript’s || (boolean or) operator, vs. C’s version of the same which returns a true/false value rather than one of its operands.
You can build on this basis to do convenient memoization, which is again particularly useful for object pointers:
-(id)foo {
return _foo ?: (_foo = bar());
}
If _foo is not nil, it returns its value; otherwise it assigns to it the return value of bar() and then returns that.
In Ruby, there is a shorthand for this, too, which is ||=:
@foo ||= bar()
Roughly identical meaning: the lvalue is assigned the rvalue. In Objective-C, this could build on the above operators with ?:=
-(id)foo {
return _foo ?:= bar();
}
This has some nice properties:
1. It works anywhere the lvalue is assignable;
2. It only has to evaluate the lvalue once (for example if you’re calculating an address expensively or in a way that has side-effects);
3. There’s no need to have parentheses surrounding the rvalue, which I always add a) out of paranoia, since I can never remember the relative precedence of ?: and =, and b) for clarity’s sake, in case someone else can’t remember the precedence either;
4. It looks like an emoticon for a walrus with an Elvis quiff. Anything we can do to promote this in our language is justified.
Thank you for your time.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
Duplicated as 12416137
Duplicated as 11826084