I've been learning ruby as of late and am basically in love with the ||= feature as it would make writing lazy getters much easier in Objective C.
Currently I write getters such as:
- (NSArray *)myArray {
if (!_myArray) {
_myArray = [NSArray array];
}
return _myArray
}
Unless im missing something with the ||= I would be able to write the previous code in Ruby using:
- (NSArray *)myArray {
return _myArray ||= [NSArray array];
}
Thats obviously much cleaner. Is there anything at all in the Objective-C language/runtime that would enable you to do this?
Also, the following is a one line ternary for getters, im not sure if its as effective as the tried and true method posted above (first snippet). Can someone tell me if theres anything wrong with doing:
- (NSArray *)myArray {
return _myArray = _myArray ? _myArray : [NSArray array];
}
The last snippet has the same effect as the first one you posted.
As an improvement, while there's no operator like ||=
in Objective-C, you can omit the second parameter of a ternary if operator and do
return _myArray = _myArray ?: [NSArray array];
which is exactly equivalent to
return _myArray = _myArray ? _myArray : [NSArray array];
This is a language extension supported by modern versions of both gcc and clang.
Bonus: if you want to save some more keystrokes, you can do
- (NSArray *)myArray {
return _myArray = _myArray ?: @[];
}
As a side note, skipping the middle operand can also have some benefit.
For instance in this case
id x = [self someMethod] ? [self someMethod] : [self anotherMethod];
if someMethod
evaluates to true
it will be called twice, whereas doing
id x = [self someMethod] ?: [self anotherMethod];
it will only be called once.
There's no literal equivalent, unless you want to hack on Clang. The ||
logical operator, while it short-circuits, doesn't evaluate to its operands. A macro, using the ternary conditional, will get you close:
#define NON_NIL(o, p) ((o) ? (o) : (p))
- (NSMutableArray *)myArray
{
return _myArray = NON_NIL(_myArray, [NSMutableArray array]);
}
because assignment in C sort of acts like an expression and evaluates to the assigned value.
You could actually make an OR_ASSIGN()
macro, too, but I'm going to leave that as an exercise for the utterly deranged reader.
Perhaps equally deranged would be a function:
id lazySet(id *obj; id(^valBlock)(void))
{
if( !(*obj) ){
*obj = valBlock();
}
return *obj;
}
- (NSMutableArray *)myArray
{
return lazySet(&_myArray, ^{return [NSMutableArray array]});
}
but that's just getting ridiculous.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With