【问题标题】:Double splat on `nil``nil` 上的双重 splat
【发布时间】:2015-12-07 03:04:18
【问题描述】:

我的理解是,非数组对象上的单个 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 的想法哪里错了。

【问题讨论】:

    标签: ruby hash literals splat double-splat


    【解决方案1】:

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

    请参阅此bug report 了解更多详情。在这个错误报告中,Ruby 的作者 Matz 宁愿删除能够 splat nil 的功能,也不愿在 nil 中添加双 splat。

    【讨论】:

    • 这是一个很好的解释——就像指向错误的指针和 Matz 的视图一样。
    【解决方案2】:

    *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 }
    

    【讨论】:

    • 那么,您是说不是to_h,而是to_hash 适用于双拼?我认为放置一个 splat 是显式的类转换,因此它是 to_a 而不是 to_ary(我的理解是 to_a 是显式的,to_ary 是隐式的),但它看起来像是我的那部分想法是错误的。
    • 是的,splat 是隐式的,不是显式的转换。
    • 这与this question 接受的答案相矛盾。这个答案错了​​吗?
    • 它也与您链接的 weblog post 相矛盾。
    • 是的,看来我弄错了。我已经编辑了我的答案以使其准确,尽管您的态度和您对我的答案的编辑表明您可能应该自己研究并回答这个问题。
    猜你喜欢
    • 2014-07-22
    • 2017-08-18
    • 2013-08-19
    • 2020-03-13
    • 2017-08-06
    • 2015-01-14
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    相关资源
    最近更新 更多