Двойной знак "ноль"
Насколько я понимаю, что один знак без объекта массива вызывает 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 }