Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `1i.to_i` raise `RangeError` instead of `NoMethodError`?

Tags:

ruby

NoMethoError is raised by to_i simply because the class doesn't have the method:

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

Surely enough, 1i has the method to_i and to_f, so it responds to them. But in reality this looks very tricky.

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

From where does the Range class come in here?

like image 932
S.Goswami Avatar asked Dec 11 '22 03:12

S.Goswami


1 Answers

Surely enough, 1i has the method .to_i and .to_f so it responds to them. But in reality this looks very tricky!

Yes, it responds to them. And when you invoke to_i on the complex literal 1i, that method throws a RangeError. That has nothing to do with the Range class; it is telling you that although 1i has a to_i method from class Complex, its specific value is not one for which a meaningful result can be obtained.

Or to put it another way, that's what Complex::to_i does when invoked on an object whose imaginary part is nonzero or even inexact:

to_i → integer

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

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

A RangeError communicates roughly that an argument is outside the range of the function to which it was provided, i.e. in the mathematical sense of "range". Complex is a bit unusual in applying that sense of "range" to the target object, as opposed to a method argument, but it nevertheless makes sense.

like image 55
John Bollinger Avatar answered Feb 23 '23 12:02

John Bollinger