Какова наука о том, что метод to_i в экземплярах Ruby NilClass возвращает ноль? Возвращение nil или повышение исключения не было бы более логичным?
Ruby Nil и Zero
Ответ 1
NilClass
определяет #to_i
по той же причине, что и определяет #to_a
, который возвращает [].
. Он дает вам что-то типа нужного, но пустое значение.
Это действительно очень полезно. Например:
<%= big.long.expr.nil? ? "" : big.long.expr %>
становится:
<%= big.long.expr %>
Гораздо приятнее! (Erb вызывает #to_s, который для nil равен "".) И:
if how.now.brown.cow && how.now.brown.cow[0]
how.now.brown.cow[0]
else
0
end
становится:
how.now.brown.cow.to_a[0].to_i
Короткие преобразования существуют, когда требуется только представление. Длинные преобразования - это те методы, которые рубиновые ядра называют, и требуют чего-то очень близкого. Используйте их, если вы хотите проверить тип.
То есть:
thing.to_int # only works when almost Integer already. NilClass throws NoMethodError
thing.to_i # this works for anything that cares to define a conversion
Ответ 2
Он соответствует философии разрешимости Ruby (в отличие от, например, строгости Python):
nil.to_i #=> 0
"".to_i #=> 0
"123hello".to_i #=> 123
"hello".to_i #=> 0
Честно говоря, я считаю, что это чрезмерно разрешительно. Как отмечено Zabba, вы можете использовать Kernel # Integer (string) для строгого преобразования.
Ответ 3
to_i
означает "преобразовать меня в целое число, если вы можете".
Если вы хотите "если вы очень похожи на целое число, дайте мне ваше целочисленное значение, иначе дайте NoMethodError", затем используйте .to_int
.
Еще один вопрос, который задает вопрос о различии между to_i
и to_int
, to_s
по сравнению с to_str
и т.д. Сообщите мне, если вы хотите, чтобы я нашел его для вас.
Ответ 4
В протоколе to_i
говорится, что вы должны вернуть Integer
, и вы не должны возбуждать исключение. Оба ваших предложения нарушают хотя бы одно из этих правил. Таким образом, нет, они не только не были бы более логичными, они были бы просто недействительными.
Обратите внимание, что nil
не отвечает на to_int
. Если он ответил на to_int
, это действительно было бы "нелогичным".
Ответ 5
Если вы попали в Rails, вы можете использовать try
:
nil.to_i # => 0
nil.try :to_i # => nil