Ruby || = equivalent in Objective-C

I've been learning Ruby lately and mostly love the || function =, as this will make it easier to write lazy getters in Objective C.

I am currently writing getters such as:

- (NSArray *)myArray { if (!_myArray) { _myArray = [NSArray array]; } return _myArray } 

If I have not lost something with || = I, I could write the previous code in Ruby using:

 - (NSArray *)myArray { return _myArray ||= [NSArray array]; } 

This is clearly a lot cleaner. Is there anything in Objective-C language / runtime that allows you to do this?

Also, the next triple line for getters, I'm not sure if it is effective, like the try and true method posted above (first snippet). Can someone tell me if something is wrong with this:

 - (NSArray *)myArray { return _myArray = _myArray ? _myArray : [NSArray array]; } 
+6
source share
2 answers

The last fragment has the same effect as the first published.

As an improvement, while there is no operator in Objective-C such as ||= , you can omit the second parameter of the triple if statement and do

 return _myArray = _myArray ?: [NSArray array]; 

which is exactly equivalent

 return _myArray = _myArray ? _myArray : [NSArray array]; 

This is a language extension supported by modern versions of gcc and clang .

Bonus: if you want to save a few more keystrokes, you can do

 - (NSArray *)myArray { return _myArray = _myArray ?: @[]; } 

As a side note, skipping the middle operand may also be useful.

For example, in this case

 id x = [self someMethod] ? [self someMethod] : [self anotherMethod]; 

if someMethod evaluates to true , it will be called twice, whereas

 id x = [self someMethod] ?: [self anotherMethod]; 

it will be called only once.

+10
source

There is no literal equivalent if you do not want to hack Clang . Logical operator || until it closes, evaluates its operands. Using a ternary conditional macro will force you to close:

 #define NON_NIL(o, p) ((o) ? (o) : (p)) - (NSMutableArray *)myArray { return _myArray = NON_NIL(_myArray, [NSMutableArray array]); } 

since an assignment in type C acts as an expression and evaluates the assigned value.

You could do the OR_ASSIGN() macro, but I'm going to leave this as an exercise for a completely crazy reader.

It is possible that equally a violation 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 it is just ridiculous.

+3
source

Source: https://habr.com/ru/post/956771/


All Articles