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

Ruby | |=Objective-C中的等价项,objective-c,ruby,Objective C,Ruby,我最近一直在学习ruby,我基本上爱上了| |=特性,因为它可以让在Objective C中编写懒惰的getter变得更容易 目前我编写的getter如下: - (NSArray *)myArray { if (!_myArray) { _myArray = [NSArray array]; } return _myArray } 除非我在| |=中遗漏了一些东西,否则我将能够使用以下代码在Ruby中编写前面的代码: - (NSArray *)myArray { ret

我最近一直在学习ruby,我基本上爱上了| |=特性,因为它可以让在Objective C中编写懒惰的getter变得更容易

目前我编写的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];
}

最后一个代码段与您发布的第一个代码段具有相同的效果

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

return _myArray = _myArray ?: [NSArray array];
这完全等同于

return _myArray = _myArray ? _myArray : [NSArray array];
这是由和的现代版本支持的语言扩展

奖励:如果你想保存更多的击键,你可以这样做

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

另外,跳过中间操作数也有一些好处

例如,在这种情况下

id x = [self someMethod] ? [self someMethod] : [self anotherMethod];
如果
someMethod
的计算结果为
true
,它将被调用两次,而

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

它将只被调用一次。

除非您愿意,否则没有文本等价物。
|
逻辑运算符在短路时不计算其操作数。使用三元条件的宏将使您接近:

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

- (NSMutableArray *)myArray
{
    return _myArray = NON_NIL(_myArray, [NSMutableArray array]);
}
因为C排序中的赋值类似于表达式,计算结果为赋值

实际上,您也可以制作一个
或\u ASSIGN()
宏,但我将把它作为一个练习留给完全精神错乱的读者

也许同样疯狂的是一种功能:

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

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

但这太荒谬了。

迷人但可怕,而且看起来有点丑陋。不管怎样,我刚刚学会了一个新词:精神错乱。在接下来的几天里,我肯定会滥用它。谢谢你的英语课。哦,你可以使用“missing middle”
?:
运算符来改进第一个宏。@Gabriele!(谢谢你指出这一点。我有一点,也许是不合理的偏好,不忽略中间的操作数。)我想这是一个品味问题,尽管我相信这是一个安全的构造,它有时可以节省方法调用(参见我的答案)。@GabrielePetronella:没错,避免双重计算可能很重要。我非常喜欢这个,提供对我的三元数据的验证,并对其进行改进。好东西。虽然很不幸,但实际上没有,但是,认为Objul-C是比Ruby更古老的语言。此外,作为原始C语言上的一层薄薄的一层,我同意不在语言中引入任何“无关”操作符的设计选择。虽然我不知道目标C,但您不想使用
\u myArray=[NSArray array]在类构造函数或初始化方法中?同样,一个不了解目标C的人可能会提出这样一个建议:请注意,如果您关心线程安全,以上所有内容都是不正确的。多线程引入了这样一种可能性:线程a可以调用setter,使非nil测试失败,然后被线程B抢先,线程B也会调用setter并使非nil测试失败。两个线程都决定创建一个新的、独立的--
NSArray
并将其存储在
\u myArray
中;欢闹随之而来。