To_i

Hi,

taken from the ruby book:

str.to_i -> anInteger

Returns the result of interpreting leading characters in str as a decimal
integer. Extraneous characters past the end of a valid number are ignored.
If there is not a valid number at the start of str, 0 is returned. The
method never raises an exception.

example
"hello".to_i
»
0

Is there a way to recognize if the conversion was successful? If
"0".to_i and “any string”.to_i deliver the same result, I don’t see how
this could be accomplished, without separately checking the syntax of the
given string.

Why doesn’t “hello”.to_i deliver a nil as a return value, which can
clearly be recognized as a conversion failure?

Artur

···

Artur Merke
>>> artur.merke@udo.edu
(O-O)
_________________________.oo0–()–0oo.

Is there a way to recognize if the conversion was successful? If
“0”.to_i and “any string”.to_i deliver the same result, I don’t see how
this could be accomplished, without separately checking the syntax of the
given string.

You have the method Integer to do this

svg% ruby -e ‘p Integer(“0”)’
0
svg%

svg% ruby -e ‘p Integer(“hello”)’
-e:1:in `Integer’: invalid value for Integer: “hello” (ArgumentError)
from -e:1
svg%

svg% ruby -e ‘a = Integer(“hello”) rescue 12; p a’
12
svg%

···

Guy Decoux

“Artur Merke” merke@ls1.cs.uni-dortmund.de schrieb im Newsbeitrag
news:Pine.LNX.4.33.0311101726040.17966-100000@as0203.cs.uni-dortmund.de
Hi,

taken from the ruby book:

str.to_i -> anInteger

Returns the result of interpreting leading characters in str as a decimal
integer. Extraneous characters past the end of a valid number are ignored.
If there is not a valid number at the start of str, 0 is returned. The
method never raises an exception.

example
"hello".to_i
»
0

Is there a way to recognize if the conversion was successful? If
"0".to_i and “any string”.to_i deliver the same result, I don’t see how
this could be accomplished, without separately checking the syntax of the
given string.

Why doesn’t “hello”.to_i deliver a nil as a return value, which can
clearly be recognized as a conversion failure?

IMHO this is a struggle between convenience and cleanness.  I guess

Matz decided for convenience in this case, maybe because in most cases
using 0 is ok. If you want to do correct input checking you do
/^[±]?\d+$/ =~ foo anyway.

Kind regards

    robert

“Artur Merke” merke@ls1.cs.uni-dortmund.de schrieb im Newsbeitrag
news:Pine.LNX.4.33.0311101726040.17966-100000@as0203.cs.uni-dortmund.de
[snip]
Why doesn’t “hello”.to_i deliver a nil as a return value, which can
clearly be recognized as a conversion failure?

IMHO this is a struggle between convenience and cleanness.  I guess

Matz decided for convenience in this case, maybe because in most cases
using 0 is ok. If you want to do correct input checking you do
/[1]?\d+$/ =~ foo anyway.

Something like this:

expand -t2 c.rb
def atoi(str)
return str.to_i if /^\d+$/ =~ str
raise “Cannot convert”
end

p atoi(“42”) #-> 42
#p atoi(“i18n”) #-> exception
#p atoi(“0.42”) #-> exception

···

On Mon, 10 Nov 2003 17:44:36 +0100, Robert Klemme wrote:


  1. ± ↩︎

IMHO this is a struggle between convenience and cleanness.  I guess

Matz decided for convenience in this case, maybe because in most cases
using 0 is ok. If you want to do correct input checking you do
/[1]?\d+$/ =~ foo anyway.

IMO, it has to do with the principle of least surprise, and it is a BIG
surprise to get
“hello”.to_i → 0
I think this should be viewed more general (not just for the methods to_i,
to_f etc.). If the application of a method makes no sense for an input,
then a nil value makes more sense as a return value (and shouldn’t
surprise anybody), then an arbitrary ambiguous value.

Artur


  1. ± ↩︎

“Artur Merke” merke@ls1.cs.uni-dortmund.de schrieb im Newsbeitrag
news:Pine.LNX.4.33.0311111240420.23480-100000@as0203.cs.uni-dortmund.de

IMHO this is a struggle between convenience and cleanness.  I

guess

Matz decided for convenience in this case, maybe because in most cases
using 0 is ok. If you want to do correct input checking you do
/[1]?\d+$/ =~ foo anyway.

IMO, it has to do with the principle of least surprise, and it is a BIG
surprise to get
“hello”.to_i → 0
I think this should be viewed more general (not just for the methods
to_i,
to_f etc.).

This is clearly dependent on the nature of the expectations, as your
posting demonstrates. If you expect to_i to return a number you’d be very
surprised to find nil there and see something like this:

14:04:17 [extranet]: ruby -e ‘1 + nil’
-e:1:in `+': nil can’t be coerced into Fixnum (TypeError)
from -e:1
14:13:25 [extranet]:

If the application of a method makes no sense for an input,
then a nil value makes more sense as a return value (and shouldn’t
surprise anybody), then an arbitrary ambiguous value.

It might very well be that in most cases using 0 as value is ok. I’m not
in a position to estimate the amounts of either sort of situation. I just
guess that Matz decided to do it this way. IMHO both solutions can be
justified. Moreover, there’s a third solution equally reasonable: make
to_i throw an exception if the instance at hand cannot be converted into a
number.

But in a way returning nil or throwing an exception would break the
pattern of the to_XYZ methods: they always return something. Even to_a
creates an array if the instance at hand is not a collection type at all.
If to_a would return nil or throw in those cases you’d always have to do
error checking, which you don’t have to with the current implementation:

def print_all(obj)
obj.to_a.each {|e| puts e}
end

This works with all instances equally well because to_a behaves the way it
does.

Often there are more reasonable solutions and one has to pick one. In
this case it defeats your expectations but maybe it doesn’t for many
others…

Kind regards

robert

  1. ± ↩︎

http://www.cplusplus.com/ref/cstdlib/atoi.html

It is common for integer conversion techniques to use only what is known
(e.g., “123hello” => 123; “hello” => 0). Delphi’s StrToInt method, however,
will throw an error (in some silly cases, IMO).

-austin

···

On Mon, 17 Nov 2003 10:24:58 +0900, Artur Merke wrote:

IMHO this is a struggle between convenience and cleanness. I guess
Matz decided for convenience in this case, maybe because in most cases
using 0 is ok. If you want to do correct input checking you do /[1]?\d+$/ =~ foo anyway.

IMO, it has to do with the principle of least surprise, and it is a BIG
surprise to get “hello”.to_i → 0


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.11.16
* 23.21.40


  1. ±
    ↩︎

Hi!

  • Artur Merke; 2003-11-17, 14:20 UTC:

IMO, it has to do with the principle of least surprise, and it is a
BIG surprise to get
“hello”.to_i → 0

Let me quote Kernighan & Richie, Programming in C (naive
implementation of atoi):

int atoi(char s)
{
int i, n;

n = 0;
for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
    n = 10 * n + (s[i] - '0');
return n;

}

Assuming this sample implementation it is not at all surprising that
atoi returns 0 if the argument string does not start with a ‘digit’.
Given Ruby’s C heritage it is no surprise that to_i behaves the same
as atoi.

Josef ‘Jupp’ Schugt

···


.-------.
message > 100 kB? / | |
sender = spammer? / | R.I.P.|
text = spam? / | |

Hi,

you don’t really want to compare ruby with c! BTW, what you have overlooked
is the fact, that c doesn’t have a nil return value (0 is only a nil value
in connection with pointers, not integers), so Kernighan & Richie havn’t
had another option then to return 0, but in ruby you have a nil value, and
I’m pretty sure ;-), K&R would have chosen to return nil in ruby’s to_i
method.

Artur

···

On Tue, 18 Nov 2003, Josef ‘Jupp’ SCHUGT wrote:

Hi!

  • Artur ; 2003-11-17, 14:20 UTC:

IMO, it has to do with the principle of least surprise, and it is a
BIG surprise to get
“hello”.to_i → 0

Let me quote Kernighan & Richie, Programming in C (naive
implementation of atoi):

int atoi(char s)
{
int i, n;

n = 0;
for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
    n = 10 * n + (s[i] - '0');
return n;

}

Assuming this sample implementation it is not at all surprising that
atoi returns 0 if the argument string does not start with a ‘digit’.
Given Ruby’s C heritage it is no surprise that to_i behaves the same
as atoi.

Josef ‘Jupp’ Schugt

                    .-------.

message > 100 kB? / | |
sender = spammer? / | R.I.P.|
text = spam? / | |

“Artur Merke” merke@ls1.cs.uni-dortmund.de schrieb im Newsbeitrag
news:Pine.LNX.4.33.0311191036400.23486-100000@as0203.cs.uni-dortmund.de

Hi,

you don’t really want to compare ruby with c! BTW, what you have
overlooked
is the fact, that c doesn’t have a nil return value (0 is only a nil value
in connection with pointers, not integers), so Kernighan & Richie havn’t
had another option then to return 0, but in ruby you have a nil value, and
I’m pretty sure ;-), K&R would have chosen to return nil in ruby’s to_i
method.

IMHO there are three reasonable ways to deal with the situation that an item
does not correspond to an integer value:

  1. return a specific int value - notably 0.

  2. retun a specific non int value - notably nil.

  3. throw an exception.

I’d say from a theoretical point of view option 3) is the cleanest. The
exception signals that there is no int representation for the specific item
at hand. In this case I’d prefer not to have to_i in such classes and then
we get no such method error. And, we can check beforehand whether the
conversion will succeed. Drawback: code must catch the exception or do the
check or will be terminated for some values.

Option 1) is next best IMHO, because it ensures that all code will continue
to work although in some cases we will see irritating results because 0 is
the neutral element for addition but not for multiplication etc.

Option 2) is worst since it neither ensures that code works (nil is not an
integer, so math will fail) nor can we omit the check of the converted value
like we can do with exceptions:

n = item.to_i
return false if n.nil?
len = n + 5

vs.

begin
len = item.to_i + 5

rescue NoMethodError
return false
end

Note, that math might not be a too good an example because then tyically one
uses 5 + item and lets coercion to the job (i.e. throw an exception if item
can’t be coerced).

I guess that Matz decided to go for opt 1) because it is the best from a
pragmatic point of view.

Regards

robert
···

Artur

On Tue, 18 Nov 2003, Josef ‘Jupp’ SCHUGT wrote:

Hi!

  • Artur ; 2003-11-17, 14:20 UTC:

IMO, it has to do with the principle of least surprise, and it is a
BIG surprise to get
“hello”.to_i → 0

Let me quote Kernighan & Richie, Programming in C (naive
implementation of atoi):

int atoi(char s)
{
int i, n;

n = 0;
for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
    n = 10 * n + (s[i] - '0');
return n;

}

Assuming this sample implementation it is not at all surprising that
atoi returns 0 if the argument string does not start with a ‘digit’.
Given Ruby’s C heritage it is no surprise that to_i behaves the same
as atoi.

Josef ‘Jupp’ Schugt

                    .-------.

message > 100 kB? / | |
sender = spammer? / | R.I.P.|
text = spam? / | |

Hi!

No TOFU (Text on-top of full quote) please, thank you.

  • Artur Merke; 2003-11-19, 13:45 UTC:

you don’t really want to compare ruby with c! BTW, what you have
overlooked is the fact, that c doesn’t have a nil return value (0
is only a nil value in connection with pointers, not integers), so
Kernighan & Richie havn’t had another option then to return 0, but
in ruby you have a nil value, and I’m pretty sure ;-), K&R would
have chosen to return nil in ruby’s to_i method.

They wouldn’t because nil is an instance of NilClass not an instance
of String. It would be a big surprise if a method sometimes returns
this class and sometimes returns that class (unless of course one
class is a subclass of the other one or both classes have a common
superclass).

I therefore expect to_i to behave like to_s, the latter defaulting to
“” if no senseful representation is being found. If to_s returns
string version of nothing in such cases it would be a big surprise if
to_i would not return the numerical version of nothing - which is 0.

The obvious alternative to returning something unexpected is to raise
an exception indicating that something unexpected was encountered. It
would make perfect sense if to_i would raise an ArgumentError. For
this reason there are two ways of convering strings to numbers.

  • Sending the to_i message is the non-exception-throwing variant.

  • Applying the Integer operator is the exception-throwing variant.

Just my 0.02 EUR,

Josef ‘Jupp’ Schugt

···


.-------.
message > 100 kB? / | |
sender = spammer? / | R.I.P.|
text = spam? / | |

Hi,

···

In message “Re: to_i” on 03/11/20, “Robert Klemme” bob.news@gmx.net writes:

I guess that Matz decided to go for opt 1) because it is the best from a
pragmatic point of view.

I provided both (to_i for opt1, Integer() for opt2).

						matz.