Ruby || = equivalente en Objective-C

He estado aprendiendo Ruby en los últimos tiempos y estoy básicamente enamorado de la función || = ya que haría mucho más fácil escribir a los perezosos en el Objetivo C.

Actualmente escribo getters como:

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

A menos que me esté perdiendo algo con el || = podría escribir el código anterior en Ruby usando:

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

Eso es obviamente mucho más limpio. ¿Hay algo en absoluto en el lenguaje / tiempo de ejecución de Objective-C que le permita hacer esto?

Además, el siguiente es un ternario de una línea para los captadores, no estoy seguro de si es tan efectivo como el método probado y verdadero publicado anteriormente (primer fragmento). Alguien puede decirme si hay algo malo con hacer:

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

El último fragmento tiene el mismo efecto que el primero que publicaste.

Como mejora, si bien no hay un operador como ||= en Objective-C, puede omitir el segundo parámetro de un ternario si el operador y hacer

 return _myArray = _myArray ?: [NSArray array]; 

que es exactamente equivalente a

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

Esta es una extensión de lenguaje compatible con versiones modernas de gcc y clang .

Bonificación: si desea guardar más pulsaciones de teclas, puede hacerlo

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

Como nota al margen, saltarse el operando del medio también puede tener algún beneficio.

Por ejemplo, en este caso.

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

si someMethod evalúa como true , se llamará dos veces, mientras que hacerlo

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

Sólo se llamará una vez.

No hay un equivalente literal, a menos que quieras piratear a Clang . El || El operador lógico, aunque cortocircuita, no evalúa a sus operandos. Una macro, utilizando el condicional ternario, te acercará:

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

porque la asignación en C actúa como una expresión y se evalúa al valor asignado.

También podrías crear una macro OR_ASSIGN() , pero voy a dejar eso como un ejercicio para el lector completamente desquiciado.

Tal vez igualmente alterada sería una función:

 id lazySet(id *obj; id(^valBlock)(void)) { if( !(*obj) ){ *obj = valBlock(); } return *obj; } - (NSMutableArray *)myArray { return lazySet(&_myArray, ^{return [NSMutableArray array]}); } 

Pero eso se está volviendo ridículo.