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.