在'nil`

时间:2015-12-07 03:04:19

标签: ruby hash literals splat double-splat

我的理解是,非数组对象上的单个splat调用to_a,然后将元素分开。由于nil.to_a定义为[],因此会发生以下转换:

[:foo, *nil, :bar]
# => [:foo, *nil.to_a, :bar]
# => [:foo, *[], :bar]
# => [:foo, :bar]

通过类比,我认为非哈希对象上的双重splat调用to_h然后将键值对分开。由于nil.to_h被定义为{},因此我预计会发生以下转换:

{"foo" => 1, **nil, "bar" => 2}
# => {"foo" => 1, **nil.to_h, "bar" => 2}
# => {"foo" => 1, **{}, "bar" => 2}
# => {"foo" => 1, "bar" => 2}

但实际上,它会引发错误:no implicit conversion of nil into Hash。为什么它会像那样?

编辑我不是在询问设计背后的原因。我问的是关于双重splat我的想法是错误的。

2 个答案:

答案 0 :(得分:2)

这是我们人类识别模式和预测事物的超能力。然而,并非总是如此。这是一个例子。 Ruby在splat和double splat中并不一致。你的思维方式是一种“记住”的好方法,但它并不完全是Ruby在splats上工作的方式。

有关更多详细信息,请参阅此bug report。在这个错误报告中,Ruby的作者Matz宁愿删除能够展开nil而不是向nil添加双splat的功能。

答案 1 :(得分:1)

*nil有效的原因是因为splat运算符可以处理响应to_a的任何内容,而nil.to_a会返回[]**nil无效的原因是nil没有回复to_hash to_a,这是NilClass的双重对等。

如果您想要这种行为,可以修补class NilClass def to_hash {} end end { "foo" => 1, **nil, "bar" => 2 } # => { "foo" => 1, "bar" => 2 }

UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *) self.collectionView.collectionViewLayout;
flowLayout.estimatedItemSize = CGSizeMake(estimatedWidth, estimatedHeight)];