2013-10-26 3 views
6

Я изучаю рубин в последнее время, и я в основном в любви с || = функцией, как это сделало бы писать ленивые добытчик гораздо проще в Objective C.рубин || = эквивалент в Objective-C

В настоящее время Я пишу добытчиками, такие как:

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

Если им не хватает чего-то с || = я смог бы написать предыдущий код в Ruby, используя:

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

То, очевидно, намного чище. Есть ли что-нибудь вообще в языке Objective-C/runtime, который позволит вам это сделать?

Кроме того, следующая тройная тройка для геттеров, im не уверен, насколько эффективен метод try и true выше (первый фрагмент). Может кто-нибудь сказать мне, если Theres ничего плохого делать:

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

Хотя я не знаю Objective C, не хотите ли вы иметь '_myArray = [NSArray array];' в методе класса Constructor или initialize? Опять же, просто потенциальное предложение парня, который не знает цели C: p – David

+1

Обратите внимание, что все вышеперечисленное неверно, если вы заботитесь о безопасности потоков. –

+1

Многопоточность вводит возможность того, что Thread A может вызвать сеттер, выдать не-nil-тест, а затем быть упреждаемым потоком B, который также вызывает setter и не выполняет тест non-nil. Оба потока решили создать новый - отдельный - 'NSArray' и сохранить его в' _myArray'; начинается веселье. –

ответ

10

Последний фрагмент имеет тот же эффект, как и первый вы публикуемую.

Как улучшение, в то время как нет оператора, как ||= в Objective-C, вы можете опустить второй параметр трехкомпонентной, если оператор и сделать

return _myArray = _myArray ?: [NSArray array]; 

который точно соответствует

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

Это языковое расширение, поддерживаемое современными версиями как gcc, так и clang.

Бонус: если вы хотите сохранить еще несколько нажатий клавиш, вы можете сделать

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

Как примечание стороны, пропуская средний операнд может иметь некоторую выгоду.

К примеру, в этом случае

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

если someMethod вычисляет true она будет называться дважды, в то время как делать

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

он будет называться только один раз.

+0

Мне это очень нравится, дает подтверждение моей тройной и улучшает ее. Хорошая вещь. Очень грустно, что нет. –

+0

Действительно, но считайте, что Objective-C намного старше, чем рубин. Более того, будучи таким тонким слоем над оригинальным C, я согласен с выбором дизайна, не вводя какого-либо «постороннего» оператора в язык. –

3

Существует не буквальный эквивалент, если вы не хотите hack on Clang. Логический оператор ||, пока он закорочен, не оценивает его операнды. Макрос, используя тройное условна, получите вы закроете:

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

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

потому, что назначение в C рода действует как выражение и вычисляется в присвоенное значение.

Вы также можете сделать макрос OR_ASSIGN(), но я собираюсь оставить это как упражнение для совершенно ненормального читателя.

Возможно, столь же ненормальный будет функция:

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

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

но это просто становится смешно.

+0

увлекательный, но страшный и вроде уродливый, чтобы видеть. Во всяком случае, я только что узнал новое слово: ненормальное. В ближайшие дни я буду злоупотреблять им. Спасибо за английский урок. –

+0

О, и вы можете улучшить первый макрос, используя оператор «missing-middle» '?:' –

+0

Мое удовольствие, @Gabriele! (Спасибо, что указали это. У меня есть небольшое, возможно, иррациональное предпочтение, чтобы не оставлять средний операнд.) –

Смежные вопросы