2013-10-26 16 views
6

Ho imparato rubino come di ritardo e sono sostanzialmente in amore con il || = funzione in quanto renderebbe la scrittura getter pigri molto più facile in Objective C.Rubino || = equivalente in Objective-C

Attualmente scrivo getter quali:

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

a meno im manca qualcosa con il || = sarei stato in grado di scrivere il codice precedente in Ruby utilizzando:

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

Questo è, ovviamente, molto più pulito. C'è qualcosa nel linguaggio/runtime Objective-C che ti permetterebbe di fare questo?

Inoltre, il seguente è un ternario a una riga per i getter, non sono sicuro che sia efficace come il metodo provato e vero pubblicato sopra (primo frammento). Qualcuno può dirmi se c'è qualcosa di sbagliato nel fare:

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

Anche se non conosco l'Objective C, non si desidera avere '_myArray = [array NSArray];' in un costruttore Costruttore o metodo di inizializzazione? Ancora una volta, solo un potenziale suggerimento da parte di un ragazzo che non conosce l'Obiettivo C: p – David

+1

Nota che tutto quanto sopra non è corretto se ti interessa la sicurezza dei thread. –

+1

Il multithreading introduce la possibilità che il thread A possa chiamare il setter, fallire il test non nullo, e quindi essere prevenuto dal thread B, che chiama anche il setter e fallisce il test non nullo. Entrambi i thread hanno deciso di creare un nuovo - separato - 'NSArray' e di memorizzarlo in' _myArray'; segue l'ilarità. –

risposta

10

L'ultimo frammento ha lo stesso effetto come il primo che hai postato.

Come un miglioramento, mentre non c'è nessun operatore come ||= in Objective-C, è possibile omettere il secondo parametro di un ternario se l'operatore e fare

return _myArray = _myArray ?: [NSArray array]; 

che è esattamente equivalente a

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

Questa è un'estensione di linguaggio supportata dalle versioni moderne di entrambi gcc e clang.

Bonus: se si desidera salvare alcuni più combinazioni di tasti, si può fare

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

Come nota a margine, saltando l'operando mezzo può anche avere qualche beneficio.

Per esempio, in questo caso

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

se someMethod viene valutato come true sarà chiamato due volte, mentre facendo

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

sarà chiamato solo una volta.

+0

Mi piace molto, fornisce la convalida del mio ternario e mi migliora. Roba buona. Molto triste non esiste || = però. –

+0

In effetti, ma considera che l'Objective-C è una lingua molto più antica del rubino. Inoltre, essendo uno strato così sottile rispetto all'originale C, concordo con la scelta progettuale di non introdurre alcun operatore "estraneo" alla lingua. –

3

Non esiste un equivalente letterale, a meno che non si desideri hack on Clang. L'operatore logico ||, mentre cortocircuito, non valuta i suoi operandi. Una macro, utilizzando il condizionale ternario, otterrà si chiude:

#define NON_NIL(o, p) ((o) ? (o) : (p)) 

- (NSMutableArray *)myArray 
{ 
    return _myArray = NON_NIL(_myArray, [NSMutableArray array]); 
} 

perché assegnamento in C sorta di atti come un'espressione e restituisce il valore assegnato.

Si potrebbe anche fare una macro OR_ASSIGN(), ma ho intenzione di lasciarlo come esercizio per il lettore completamente squilibrato.

forse altrettanto squilibrato sarebbe una funzione:

id lazySet(id *obj; id(^valBlock)(void)) 
{ 
    if(!(*obj)){ 
     *obj = valBlock(); 
    } 
    return *obj; 
} 

- (NSMutableArray *)myArray 
{ 
    return lazySet(&_myArray, ^{return [NSMutableArray array]}); 
} 

, ma questo è solo diventando ridicolo.

+0

affascinante ma spaventoso e un po 'brutto da vedere. Ad ogni modo ho appena imparato una nuova parola: deranged. Ne approfitterò sicuramente nei prossimi giorni. Grazie per la lezione di inglese. –

+0

Oh e puoi migliorare la prima macro usando "missing-middle" '?:' Operator –

+0

My pleasure, @Gabriele! (Grazie per averlo sottolineato. Ho una leggera, forse-irrazionale preferenza per non tralasciare l'operando medio.) –