Ruby || = Objective-C中的等价物

时间:2013-10-26 03:08:38

标签: objective-c ruby

我最近一直在学习ruby,基本上爱上了|| = feature,因为它会让Objective C中的懒惰getter变得更容易。

目前我写的是吸气剂,如:

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

除非我遗漏了|| =的东西,否则我可以用Ruby编写以前的代码:

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

这显然更清洁了。 Objective-C语言/运行时中是否有任何可以实现此功能的内容?

此外,以下是getter的单行三元组,我不确定它是否与上面发布的尝试和真实方法一样有效(第一个片段)。如果有人做错了,有人可以告诉我:

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

2 个答案:

答案 0 :(得分:11)

最后一个片段与您发布的第一个片段效果相同。

作为改进,虽然Objective-C中没有像||=这样的运算符,但您可以省略三元if运算符的第二个参数并执行

return _myArray = _myArray ?: [NSArray array];

完全等同于

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

这是gccclang的现代版本支持的语言扩展程序。

奖励:如果你想节省更多的击键,你可以做

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

作为旁注,跳过中间操作数也可以带来一些好处。

例如在这种情况下

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

如果someMethod评估为true,则会调用两次,而执行

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

它只会被调用一次。

答案 1 :(得分: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]});
}

但这太荒谬了。