Подтвердить что ты не робот

Ruby Nil и Zero

Какова наука о том, что метод to_i в экземплярах Ruby NilClass возвращает ноль? Возвращение nil или повышение исключения не было бы более логичным?

4b9b3361

Ответ 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