Forum: Ruby Is it better to have a function to test if string is a number?

E7206f97b4bf8ed12b54fb4c975ae5a7?d=identicon&s=25 陈迪豪 (Guest)
on 2014-03-11 09:49
(Received via mailing list)
So many similar functions have been implemented(refer
http://stackoverflow.com/questions/1235863/test-if...
and
http://stackoverflow.com/questions/5661466/test-if...).

But for DRY principle, is it better for Ruby to implement it? Maybe
"is_number?" or "to_i?".
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2014-03-11 11:06
(Received via mailing list)
On Tue, Mar 11, 2014 at 9:48 AM, 陈迪豪 <chendihao@xiaomi.com> wrote:
> So many similar functions have been implemented(refer
>
http://stackoverflow.com/questions/1235863/test-if...
> and
>
http://stackoverflow.com/questions/5661466/test-if...).
>
> But for DRY principle, is it better for Ruby to implement it? Maybe
> "is_number?" or "to_i?".

No. There is already one standard solution.  Best is to just use
Integer and handle the exception.

size = Integer(gets)

You can even catch in line if you really need to use this in a branch
condition

size = Integer(gets) rescue nil

if size
  printf "size is %4d\n", size
else
  $stderr.puts "did not get a number"
end

Cheers

robert
15000f55138ae94b0f362ed7c625461a?d=identicon&s=25 unknown (Guest)
on 2014-03-13 22:36
(Received via mailing list)
Am 11.03.2014 11:06, schrieb Robert Klemme:
> Integer and handle the exception.
>
> size = Integer(gets)

"Best" is a matter of taste...

I prefer using a regex instead of raising and handling an exception,
since I consider wrong user input not to be exceptional.

> You can even catch in line if you really need to use this in a branch condition
>
> size = Integer(gets) rescue nil

I strongly disagree, you should *never* do that.

Consider e.g. a stupid typo in the code, like:

  size = Integer(getss)  rescue nil

This would **not** raise any exception, but you certainly would
want it to raise one (NameError).

Regards,
Marcus
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2014-03-14 10:58
(Received via mailing list)
On Thu, Mar 13, 2014 at 10:35 PM,  <sto.mar@web.de> wrote:
>> No. There is already one standard solution.  Best is to just use
>> Integer and handle the exception.
>>
>> size = Integer(gets)
>
> "Best" is a matter of taste...

I'd say it's a matter of values: your values determine what you
consider better or worse. But of course there is a certain factor of
subjectivity here. OTOH there are best practices in the industry. :-)

> I prefer using a regex instead of raising and handling an exception,

Fact remains that you are duplicating the parsing code.  If at some
point in time what Integer() accepts as valid input changes (not very
likely in _this_ case) you have diverging implementations. Redundancy
is usually bad. Maybe it's a bit more obvious with floating point
numbers as the regexp to parse that is significantly more complex. You
don't really want

> since I consider wrong user input not to be exceptional.

Well, nobody said you need to let the exception escape the user input
routine. Advantage of using exceptions is that you only have one
operation (the conversion to int) and proceed normally if it succeeds;
if it fails you take another code path.

Usually it's better to execute an operation and deal with failure than
to try to determine whether it will work, execute it - and still have
to deal with failure.  This is especially true for situations where
conditions can change between the check and the operation which allow
the operation still to fail. Typical example is: you check network
connectivity (e.g. to a database) and then do the actual connection.
You always have to deal with potential connection failures, even if
the check succeeded.  So you are making the code more complicated and
do not gain anything.

> This would **not** raise any exception, but you certainly would
> want it to raise one (NameError).

That will be apparent quite soon during testing. You'll also get
another exception when using the object as an integer.

$ ruby -e '2 + nil'
-e:1:in `+': nil can't be coerced into Fixnum (TypeError)
        from -e:1:in `<main>'
$ ruby -e 'nil + 2'
-e:1:in `<main>': undefined method `+' for nil:NilClass (NoMethodError)

Kind regards

robert
15000f55138ae94b0f362ed7c625461a?d=identicon&s=25 unknown (Guest)
on 2014-03-15 22:49
(Received via mailing list)
Am 14.03.2014 10:57, schrieb Robert Klemme:
> On Thu, Mar 13, 2014 at 10:35 PM,  <sto.mar@web.de> wrote:
>> Am 11.03.2014 11:06, schrieb Robert Klemme:
[...]
>>> No. There is already one standard solution.  Best is to just use
>>> Integer and handle the exception.
>>>
>>> size = Integer(gets)
>>
>> "Best" is a matter of taste...
>
> I'd say it's a matter of values: your values determine what you
> consider better or worse. But of course there is a certain factor of
> subjectivity here. OTOH there are best practices in the industry. :-)

I did not want to start a discussion on pros and cons of both
versions, that's why I said matter of taste :)
There is also "best practice" of not using exceptions for flow control.
Again opinions diverge.

[...]
> Usually it's better to execute an operation and deal with failure than
> to try to determine whether it will work, execute it - and still have
> to deal with failure.  This is especially true for situations where
> conditions can change between the check and the operation which allow
> the operation still to fail. Typical example is: you check network
> connectivity (e.g. to a database) and then do the actual connection.
> You always have to deal with potential connection failures, even if
> the check succeeded.  So you are making the code more complicated and
> do not gain anything.

Agreed, but that doesn't really apply here.
The "integerness" of a string is not likely to change :)

>> This would **not** raise any exception, but you certainly would
>> want it to raise one (NameError).
>
> That will be apparent quite soon during testing. You'll also get
> another exception when using the object as an integer.

The problem I wanted to point out is that with "rescue nil" you could
not distinguish between 1) bad user input and 2) any other problem.
For more intricate situations that might not be so easily detected
during tests, e.g. timeouts from a network connection. Happy debugging!

"rescue nil" is widely considered to be a code smell.

Regards,
Marcus
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.