我的理解是,非数组对象上的单个 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
.为什么它表现得那样?
编辑我不是在问设计背后的原因。我问我对双喷板的想法哪里是错误的。
这是我们人类识别模式和预测事物的超能力。然而,这并不总是正确的。这是一个例子。Ruby 在 splat 和 double splat 中并不一致。你的思维方式是"记住"的好方法,但这并不完全是Ruby在splats上的工作方式。
有关更多详细信息,请参阅此错误报告。在这个错误报告中,Ruby的作者Matz宁愿删除能够拼接nil
的功能,也不愿向nil
添加双拼接。
*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 }