Почему `1i.to_i` вызывает` RangeError` вместо `NoMethodError`? - PullRequest
0 голосов
/ 21 февраля 2019

NoMethoError повышается на to_i просто потому, что у класса нет метода:

[].to_i # >> NoMethodError (undefined method `to_i' for []:Array)

Конечно, 1i имеет метод to_i и to_f, поэтомуэто отвечает им.Но на самом деле это выглядит очень сложно.

1i.respond_to?(:to_i) # => true
1i.to_i # >> RangeError (can't convert 0+1i into Integer)

Откуда сюда приходит класс Range?

Ответы [ 3 ]

0 голосов
/ 21 февраля 2019

Конечно, у 1i есть методы .to_i и .to_f, поэтому он отвечает на них.Но на самом деле это выглядит очень сложно!

Да, он отвечает на них.И когда вы вызываете to_i для сложного литерала 1i, этот метод выдает RangeError.Это не имеет ничего общего с классом Range;он говорит вам, что, хотя 1i имеет метод to_i из класса Complex, его конкретное значение не такое, для которого можно получить значимый результат.

Или, другими словами, эточто Complex::to_i делает при вызове объекта, чья мнимая часть ненулевая или даже неточная:

to_i → целое число

Возвращает значение как целое число, если это возможно (мнимая часть должна быть точно равна нулю).

Complex(1, 0).to_i    #=> 1
Complex(1, 0.0).to_i  # RangeError
Complex(1, 2).to_i    # RangeError

A RangeError примерно сообщает, что аргумент находится за пределами диапазонафункция, которой она была предоставлена, т.е. в математическом смысле «диапазон».Complex немного необычно в применении этого значения «диапазона» к целевому объекту, в отличие от аргумента метода, но, тем не менее, имеет смысл.

0 голосов
/ 21 февраля 2019

Спецификация для Complex#to_i такова, как Урсус и Джон Болингер говорят в своем ответе.

Причина, по которой Complex#to_i определена (и, следовательно, не вызывает ошибку NoMethoError), заключается в том, что она возвращаетРасчетное значение, когда мнимая часть не равна нулю, и, следовательно, его необходимо определить.Вы не можете поднять NoMethodError только для некоторых экземпляров класса.

Причина, по которой оно не вызывает более знакомое исключение, скажем ArgumentError, заключается в том, что это не аргумент, априемник.

Чтобы выдать ошибку для определенных экземпляров класса, наилучшее совпадение получилось RangeError;нет другого Exception класса, который, кажется, подходит лучше.

0 голосов
/ 21 февраля 2019

Документация гласит:

Returns the value as an integer if possible (the imaginary part should be exactly zero).

Так что это не выглядит слишком полезным, оно работает, только если i равно нулю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...