我的理解是,非数组对象上的单个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我的想法是错误的。
答案 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)];