Двойной знак "ноль"

Насколько я понимаю, что один знак без объекта массива вызывает to_a а затем разделяет элементы на части. И с тех пор nil.to_a определяется как []происходит следующее преобразование:

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

По аналогии я подумал, что двойной знак на объекте без хеша вызывает 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, Почему он так себя ведет?

Редактировать Я не спрашиваю о причинах дизайна. Я спрашиваю, где мое мышление неправильно в отношении двойного сплата.

2 ответа

Ну, это наша сверхспособность для человека распознавать закономерности и предсказывать вещи. Однако это не всегда так. Это один из примеров. Руби непоследовательна в сплате и двойном сплате. Ваш образ мышления - это хороший способ "запомнить", но это не совсем то, как работает Ruby на сплатах.

Смотрите этот отчет об ошибке для более подробной информации. В этом отчете об ошибке автор Ruby, Matz, скорее убрал возможность разбрызгивания nil чем добавить двойной знак nil,

Причина *nil работает потому, что оператор сплат работает на все, что отвечает 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 }
Другие вопросы по тегам