string to int: ruby documentation?

7

7stud 7stud

Hi,

In trying to convert a string to an integer, I found this passage in the
ruby documentation:
http://dev.rubycentral.com/ref/

-------------
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.
-------------

That description seems complete. It talks about edge cases, and what
happens, and that the method doesn't throw an exception. Then I found
this passage:

-----------
Integer( arg ) -> anInteger

Converts arg to a Fixnum or Bignum. Numeric types are converted directly
(with floating point numbers being truncated). If arg is a String,
leading radix indicators (0, 0b, and 0x) are honored. This behavior is
different from that of String#to_i.
------------

In that description, there is no mention of exceptions that can be
thrown, but when I try the Integer() method, this is the output:

irb(main):002:0> Integer("10")
=> 10
irb(main):003:0> Integer("10abc")
ArgumentError: invalid value for Integer: "10abc"
from (irb):3:in `Integer'
from (irb):3
irb(main):004:0> Integer("hello")
ArgumentError: invalid value for Integer: "hello"
from (irb):4:in `Integer'
from (irb):4
irb(main):005:0>

So, it seems pretty clear that the Integer() method can throw an
ArgumentError exception, and I'm wondering why the docs don't mention
what exceptions Integer() throws? Is that typical of the docs? If it
doesn't say "no exceptions are thrown", should I assume it can throw
some as yet unidentified exception?
 
E

eden li

irb(main):036:0> Class.constants.map { |c| eval(c).new rescue
nil }.compact.map { |s| Integer(s) rescue $! }.select { |c| c.is_a?
(Exception) }.map { |c| c.class }.uniq
=> [TypeError, ArgumentError, NoMethodError]

Looks like it could TypeError and NoMethodError as well...
 
7

7stud 7stud

Eden said:
irb(main):036:0> Class.constants.map { |c| eval(c).new rescue
nil }.compact.map { |s| Integer(s) rescue $! }.select { |c| c.is_a?
(Exception) }.map { |c| c.class }.uniq
=> [TypeError, ArgumentError, NoMethodError]

Looks like it could TypeError and NoMethodError as well...

So the docs don't "document" which exceptions can be thrown by a method?
 
G

Gary Wright

Eden said:
irb(main):036:0> Class.constants.map { |c| eval(c).new rescue
nil }.compact.map { |s| Integer(s) rescue $! }.select { |c| c.is_a?
(Exception) }.map { |c| c.class }.uniq
=> [TypeError, ArgumentError, NoMethodError]

Looks like it could TypeError and NoMethodError as well...

So the docs don't "document" which exceptions can be thrown by a
method?

The documentation isn't perfect. There is information about
contributing
to Ruby documentation at www.ruby-doc.org.

It has been my observation that the Ruby style is to avoid the use
of exceptions as part of the expected behavior of a method. What I mean
is that, in general, if you provide arguments to a method that meet the
method's pre-conditions then you will get back a result with no
exception
being raised. If you provide arguments that *don't* meet the
pre-conditions of a method, well then you may or may not get an
exception
but it is really your problem in either case because you violated the
pre-condition and all bets are off.

Test driven development really puts the burden on the caller to provide
the correct arguments and methods are often written with that explicit
expectation, which tends to reduce the amount of argument checking that
is done in methods.

When exceptions are explicitly part of the behavior of a method then I,
of course, think their use should be documented.

I'd be interested in other perspectives on best practices with respect
to exceptions and argument checking in API/class design.


Gary Wright
 
D

Daniel Finnie

I think this depends somewhat on your definition of an argument.

If I do "0101110".to_i(2), then clearly 2 is an argument. But is
"0101110"? Technically, no, it is the receiver. In Ruby's duck typed
world where multiple, same named methods do different things depending
on class, then it kindof is an argument.

Dan

Gary said:
Eden said:
irb(main):036:0> Class.constants.map { |c| eval(c).new rescue
nil }.compact.map { |s| Integer(s) rescue $! }.select { |c| c.is_a?
(Exception) }.map { |c| c.class }.uniq
=> [TypeError, ArgumentError, NoMethodError]

Looks like it could TypeError and NoMethodError as well...

So the docs don't "document" which exceptions can be thrown by a method?

The documentation isn't perfect. There is information about contributing
to Ruby documentation at www.ruby-doc.org.

It has been my observation that the Ruby style is to avoid the use
of exceptions as part of the expected behavior of a method. What I mean
is that, in general, if you provide arguments to a method that meet the
method's pre-conditions then you will get back a result with no exception
being raised. If you provide arguments that *don't* meet the
pre-conditions of a method, well then you may or may not get an exception
but it is really your problem in either case because you violated the
pre-condition and all bets are off.

Test driven development really puts the burden on the caller to provide
the correct arguments and methods are often written with that explicit
expectation, which tends to reduce the amount of argument checking that
is done in methods.

When exceptions are explicitly part of the behavior of a method then I,
of course, think their use should be documented.

I'd be interested in other perspectives on best practices with respect
to exceptions and argument checking in API/class design.


Gary Wright
 
G

Gary Wright

I think this depends somewhat on your definition of an argument.

If I do "0101110".to_i(2), then clearly 2 is an argument. But is
"0101110"? Technically, no, it is the receiver. In Ruby's duck
typed world where multiple, same named methods do different things
depending on class, then it kindof is an argument.

But the current state of an object can certainly be part of the pre-
condition for a method. Pre-conditions aren't entirely about the
arguments to a method.


Gary Wright
 
7

7stud 7stud

Gary said:
being raised. If you provide arguments that *don't* meet the
pre-conditions of a method, well then you may or may not get an
exception
but it is really your problem in either case because you violated the
pre-condition and all bets are off.

I gave Integer() a string and it threw an exception.
 
S

Stefano Crocco

Alle luned=C3=AC 12 marzo 2007, 7stud 7stud ha scritto:
I gave Integer() a string and it threw an exception.

A quick look at the documentation has lead me to the following consideratio=
ns:

There *are* some places where documentation about exceptions raised is trul=
y=20
missing (examples: File.read =3D> LoadError if file doesn't exist; File.wri=
te=20
=3D> SystemCallError if file isn't open for writing, and, of course Integer=
()).=20
These methods, in my opinion, need to be better documented.

Some situations are implicitly assumed to throw exceptions:
=2D passing a method an argument of a type different from the one required =
(for=20
example, a string to Fixnum#to_s), raises a TypeError exception
=2D passing a method an argument which is of the correct type, but which do=
esn't=20
fulfill al the prerequisites (for instance, passing an integer greater than=
=20
36 to Fixnum#to_s), raises an ArgumentError exception
=2D a method which should do some parsing (for instance Regexp.new or YAML.=
load)=20
raises an exception if the string doesn't contain valid code. The kind of=20
exception varies, though (Regexp.new raises a RegexpError while YAML.load=20
raises ArgumentError)

Stefano
 
G

Gary Wright

I gave Integer() a string and it threw an exception.

I muddled up a specific response to you about Integer with some
more general observations about exceptions and Ruby. Sorry I wasn't
clear:

1) Ruby documentation isn't perfect. You found a problem.
2) There are methods (i.e. Integer()) where exceptions are part
of the expected behavior of the method and they *should* be
documented. If they aren't, that is a bug not a feature.
3) Most Ruby methods don't say anything about exceptions because
exceptions are not part of the API of most Ruby methods. There
is an overall assumption that if you call a method without meeting
the pre-conditions then the behavior (including the raising of
exceptions) is undefined.
4) Pre-conditions should be clearly described by the documentation.

Gary Wright
 
7

7stud 7stud

Gary said:
I muddled up a specific response to you about Integer with some
more general observations about exceptions and Ruby. Sorry I wasn't
clear:

1) Ruby documentation isn't perfect. You found a problem.
2) There are methods (i.e. Integer()) where exceptions are part
of the expected behavior of the method and they *should* be
documented. If they aren't, that is a bug not a feature.
3) Most Ruby methods don't say anything about exceptions because
exceptions are not part of the API of most Ruby methods. There
is an overall assumption that if you call a method without meeting
the pre-conditions then the behavior (including the raising of
exceptions) is undefined.
4) Pre-conditions should be clearly described by the documentation.

Gary Wright

Ok. I was all set to buy the pickaxe book, but then I noticed that
missing documentation, so I decided to look for alternatives. I looked
in "The Ruby Way", and it mentions that Integer() throws an exception
when the string is not of the right format in a section titled something
like "Turning strings into numbers". So it looks like those books would
be good companion texts.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,733
Latest member
LonaMonzon

Latest Threads

Top