nil.to_i returning zero

  • Thread starter Gerardo Santana Gómez Garrido
  • Start date
G

Gerardo Santana Gómez Garrido

zero in Ruby is true, not false, in a boolean context.

What does false.to_i return? An exception. There is not a numeric
interpretation for false.

What about nil. nil is nothing. The only other object that evaluates
to false in a boolean context.

What does nil.to_i return? Zero. And I wonder why. How can nil be
interpreted as a number. It's beyond me.

Anyone care to explain it to me?

So far I've found the following links about the issue:

http://www.oreillynet.com/ruby/blog/2005/12/is_this_a_good_thing_or_not.html
http://journal.dedasys.com/articles/2007/05/08/rails-bitten-by-rubys-nil-to_f
http://groups.google.com/group/ruby...6945a4210?lnk=gst&q=nil.to_i#b9f0cac6945a4210
 
A

Axel Etzold

What does nil.to_i return? Zero. And I wonder why. How can nil be
interpreted as a number. It's beyond me.

Anyone care to explain it to me?

Dear Gerardo,

without claiming any particular authority, to me, this definition
of what nil.to_i should return doesn't violate the principle of least
surprise so cherished by Ruby coders - if you have nil dollars money, that's 0 dollars -- think of the balance of somebody who hasn't
opened an account at "Ruby Deposit Bank" yet --
but if you wanted nil.to_i to raise an exception,
because the "Ruby-Using Logicians Club" might be unhappy with such
elliptic thinking, I might find that reasonable also.
Maybe one has to distinguish between 0 and 1 on the one hand and
false and true on the other, when coding Ruby, right from the start,
to avoid any confusion.

Best regards,

Axel
 
J

John Joyce

nil is nothing?
well, by some thinking zero is nothing as well.
nil.to_i returning zero is convenient.


If it returned nil, then you'd get exceptions and it would be
pointless to have nil respond to to_i
Sure, nil.to_i returning nil could also make sense in a way, but it
is really a matter of making decisions about design.

It's just the way the language is.

It's not C or C++ or another language. It's Ruby.
Every language does things its own way.
this is one of those things.
 
J

Jeremy McAnally

I expect to get a converted object or some *Error (TypeError maybe?)
back from any to_* method. Giving me the same object back or nil
doesn't make any sense...

As others have noted, I think the current behavior makes sense: I have
nil (whatever...money, cats, etc.) I'd think an integer representation
would be 0.

--Jeremy

zero in Ruby is true, not false, in a boolean context.

What does false.to_i return? An exception. There is not a numeric
interpretation for false.

What about nil. nil is nothing. The only other object that evaluates
to false in a boolean context.

What does nil.to_i return? Zero. And I wonder why. How can nil be
interpreted as a number. It's beyond me.

Anyone care to explain it to me?

So far I've found the following links about the issue:

http://www.oreillynet.com/ruby/blog/2005/12/is_this_a_good_thing_or_not.h= tml
bb8a541f700e/b9f0cac6945a4210?lnk=3Dgst&q=3Dnil.to_i#b9f0cac6945a4210


--=20
http://www.jeremymcanally.com/

My books:
Ruby in Practice
http://www.manning.com/mcanally/

My free Ruby e-book
http://www.humblelittlerubybook.com/

My blogs:
http://www.mrneighborly.com/
http://www.rubyinpractice.com/
 
C

Chad Perrin

What does nil.to_i return? Zero. And I wonder why. How can nil be
interpreted as a number. It's beyond me.

There's been a few attempts to answer the question already. I'm curious,
though:

What would you expect it to return, and why would you think that should
be the expected behavior?

Nothing immediately occurs to me as a better result of evaluating
nil.to_i than 0, within the context of the Ruby language, but if you have
an alternative view I'm open to learning from it.
 
M

Michael Fellinger

There's been a few attempts to answer the question already. I'm curious,
though:

What would you expect it to return, and why would you think that should
be the expected behavior?

Nothing immediately occurs to me as a better result of evaluating
nil.to_i than 0, within the context of the Ruby language, but if you have
an alternative view I'm open to learning from it.

nil.to_i
# > NoMethodError: undefined method `to_i' for nil:NilClass
Integer(nil)
# > TypeError: can't convert nil into Integer

This is on my wish list for Christmas among other things.
 
K

Konrad Meyer

--nextPart29087866.W4Jvgm8RBk
Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Quoth Michael Fellinger:
=20
nil.to_i
# > NoMethodError: undefined method `to_i' for nil:NilClass
Integer(nil)
# > TypeError: can't convert nil into Integer
=20
This is on my wish list for Christmas among other things.

Thing is, #to_i explicitly does *not* throw errors -- that's what Integer()=
is=20
for. Current (1.8.6) ruby doesn't error on Integer(nil) either, but IMO it=
=20
should.

Regards,
=2D-=20
Konrad Meyer <[email protected]> http://konrad.sobertillnoon.com/

--nextPart29087866.W4Jvgm8RBk
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHEyCzCHB0oCiR2cwRArhXAJ0agOQaByZVkw75rbKr5wIsLvBFogCfQVo7
640i+Qu+zwpqi4snLv9MdC0=
=JpTc
-----END PGP SIGNATURE-----

--nextPart29087866.W4Jvgm8RBk--
 
T

Trans

zero in Ruby is true, not false, in a boolean context.

What does false.to_i return? An exception. There is not a numeric
interpretation for false.

What about nil. nil is nothing. The only other object that evaluates
to false in a boolean context.

What does nil.to_i return? Zero. And I wonder why. How can nil be
interpreted as a number. It's beyond me.

Anyone care to explain it to me?

In the strictest sense of what's "proper" I suppose you are right, it
ought return a NoMethodError. However more often than not it seems to
be exactly what we would want to happen anyway. If it were not for
that convenience we'd have a bunch of these all over the place:

(x ? x.to_i : 0)


Following through with this, we also have to_s =3D> "", to_a =3D> [] and
to_f =3D> 0.0. And I support adding to_h =3D> {}.

T=2E
 
R

Robert Dober

Quoth Michael Fellinger:
Thing is, #to_i explicitly does *not* throw errors -- that's what Integer() is
for. Current (1.8.6) ruby doesn't error on Integer(nil) either, but IMO it
should.
But Michael did not ask NilClass#to_i to throw an error, he did ask it
to go away :)

Now I am completely impartial on the behavior, but if nil.to_i is
confusing for some folks it might be a good idea to put it away unless
other folks really need it.
My pragmatic question is therefore:
nil.to_i usecases anyone?

Cheers
Robert
 
R

Robert Dober

zero in Ruby is true, not false, in a boolean context.

What does false.to_i return? An exception. There is not a numeric
interpretation for false.

What about nil. nil is nothing. The only other object that evaluates
to false in a boolean context.

What does nil.to_i return? Zero. And I wonder why. How can nil be
interpreted as a number. It's beyond me.

Anyone care to explain it to me?

In the strictest sense of what's "proper" I suppose you are right, it
ought return a NoMethodError. However more often than not it seems to
be exactly what we would want to happen anyway. If it were not for
that convenience we'd have a bunch of these all over the place:

(x ? x.to_i : 0)


Following through with this, we also have to_s =3D> "", to_a =3D> [] and
to_f =3D> 0.0. And I support adding to_h =3D> {}.
Hmm I really like that to_a will go away for everything than Enumerations
I think therefore that to_h is not a good idea.

You know we have Facets for this kind of stuff, you might want to have
a look at it one day ;)
R.

--=20
what do I think about Ruby?
http://ruby-smalltalk.blogspot.com/
 
J

Joachim Glauche

Robert said:
My pragmatic question is therefore:
nil.to_i usecases anyone?

I remember using it somewhere. I think I used it for catching user input
integer values like
unless val.to_i == 0; ... ; end


The nil.to_something behaviour seems logical to me:

nil.to_i = Returns the integer which represents "nothing" = 0
nil.to_s = Returns the string which represents "nothing" = ""
...
 
T

Trans

But Michael did not ask NilClass#to_i to throw an error, he did ask it
to go away :)

If it goes away you get a NoMethodError.
Now I am completely impartial on the behavior, but if nil.to_i is
confusing for some folks it might be a good idea to put it away unless
other folks really need it.
My pragmatic question is therefore:
nil.to_i usecases anyone?

def any_method(want_an_integer=nil)
@want_an_integer = want_an_integer.to_i
@want_an_integer + 1 # ... whatever ...
end

It is generally better to use nil for default parameters b/c it
reduces the potential for errors and increases the flexability of the
design. The same is true of using "to_i". If you did it otherwise:

def any_method(want_an_integer=0)
@want_an_integer = want_an_integer
@want_an_integer + 1
end

Errors would occur on calling:

any_method(nil)

and

any_method("0")

And to compensate one would have to put the flexability into the call:

any_method((some_var || 0).to_i)

Which IMO, is much less desirable.

T.
 
R

Robert Dober

I remember using it somewhere. I think I used it for catching user input
integer values like
unless val.to_i == 0; ... ; end


The nil.to_something behaviour seems logical to me:

nil.to_i = Returns the integer which represents "nothing" = 0
nil.to_s = Returns the string which represents "nothing" = ""
...
Hmm it might be a matter of taste what we can do with nil or not. I
just forgot to
think about something crucial.
nil is just different than anything else, nil can spring into life like nothing,
and then when we think we have a value in our @ivar we might just get nil.
Sometimes it is difficult to track these errors down, nil accepting
messages does
*not* make this easier.
I believe I want nil.<anything> to go away after all.
R.
 
M

mortee

Michael said:
nil.to_i
# > NoMethodError: undefined method `to_i' for nil:NilClass
Integer(nil)
# > TypeError: can't convert nil into Integer

This is on my wish list for Christmas among other things.

Well, if you'd like it so much, why not just redefine it in your own
programs? Everyone else seems to expect it to return 0 instead of being
hostile by throwing an exception...

mortee
 
C

Chad Perrin

Now I am completely impartial on the behavior, but if nil.to_i is
confusing for some folks it might be a good idea to put it away unless
other folks really need it.
My pragmatic question is therefore:
nil.to_i usecases anyone?

How about any circumstance in which one performs some kind of counting
function in code, and operates on the number of whatever is counted,
where no specific value is yet applied to the variable in question until
the first item is counted?

I suppose I find it more difficult to imagine a use case for nil.to_i
returning a no method error or throwing an exception.
 
R

Robert Dober

How about any circumstance in which one performs some kind of counting
function in code, and operates on the number of whatever is counted,
where no specific value is yet applied to the variable in question until
the first item is counted?

I suppose I find it more difficult to imagine a use case for nil.to_i
returning a no method error or throwing an exception.
unless you did not intent it to be nil, that had escaped me too.
 
T

Trans

unless you did not intent it to be nil, that had escaped me too.

That what tests are for. (Of course one could say that about anything,
but in this case I think it's the better choice.)

And of course there's always:

raise if x.nil?

T.
 
G

Gerardo Santana Gómez Garrido

John said:
If it returned nil, then you'd get exceptions and it would be
pointless to have nil respond to to_i

You got it wrong. I'm not asking for #to_i returning nil.
NilClass#to_i shouldn't be there in the first place.
Sure, nil.to_i returning nil could also make sense in a way,

Wrong. See above.

Jeremy said:
I expect to get a converted object or some *Error (TypeError maybe?)
back from any to_* method. Giving me the same object back or nil
doesn't make any sense...

You got it wrong too (am I that confusing? :).

As others have noted, I think the current behavior makes sense: I have
nil (whatever...money, cats, etc.) I'd think an integer representation
would be 0.

nil has other uses besides representing nothing: it means false in a
boolean context.

If nil
Under that logic then zero must evaluate to false, just like C and Python does.
I don't agree with that, of course.

Chand said:
What would you expect it to return, and why would you think that should
be the expected behavior?

I'd expect the same behavior as FalseClass and TrueClass: undefined method.

Because if I want 0 would expect or send 0, not nil.to_i.
Because it doesn't make sense to me that nil, which means false also,
can be represented as zero, when zero doesn't mean false, but true.

If it were not for
that convenience we'd have a bunch of these all over the place:

(x ? x.to_i : 0)

Is that so common? Maybe I haven't written that many scripts, but I can't
remember right now somewhere where I needed that. Ok, maybe parsing parameters.

NilClass#to_s actually makes some sense in a context where you want to
serialize objects; "" means exactly nothing (in that context!)
def any_method(want_an_integer=nil)
@want_an_integer = want_an_integer.to_i
@want_an_integer + 1 # ... whatever ...
end

It is generally better to use nil for default parameters b/c it
reduces the potential for errors and increases the flexability of the
design. The same is true of using "to_i". If you did it otherwise:

def any_method(want_an_integer=0)
@want_an_integer = want_an_integer
@want_an_integer + 1
end

Errors would occur on calling:

any_method(nil)

and

any_method("0")

And to compensate one would have to put the flexability into the call:

any_method((some_var || 0).to_i)

Which IMO, is much less desirable.

Maybe it's a matter of taste, but I validate parameters before calling methods,
not inside methods. If you feed unexpected parameters to a method, well, you
should get an exception. Right?

Well, if you'd like it so much, why not just redefine it in your own
programs? Everyone else seems to expect it to return 0 instead of being
hostile by throwing an exception...

Oh, c'mon ...


Chad said:
How about any circumstance in which one performs some kind of counting
function in code, and operates on the number of whatever is counted,
where no specific value is yet applied to the variable in question until
the first item is counted?

I don't think I understood you. Correct me plese, but I think you're talking
about an accumulator? In that case, you should start from zero, not nil.
 
P

Phrogz

You got it wrong. I'm not asking for #to_i returning nil.
NilClass#to_i shouldn't be there in the first place.



You got it wrong too (am I that confusing? :).

I suspect the confusion comes from the fact that your initial post was
titled "nil.to_i returning zero". Apparently the subject was a red
herring. We might have gotten more swiftly to discussing the merits of
your beliefs/suggestions had the subject been titled (for example)
"nil.to_i (and nil.to_s) should not exist".

This isn't criticism - I know well how it sometimes occurs that only
after a discussion has taken place do I realize what question or
statement I was really trying to make. The discussion is part of the
clarifying process.

So, having refocused the discussion on the question: "Should NilClass
have a #to_i method?", let me throw in my opinion:

Various objects have methods that return an instance of a different
class. The most obvious is the #to_s method. By extension, your
argument that nil.to_i should not return 0 because 0 is a truth value
would further imply that false.to_s should not return "false" because
all strings are also truth values. Is it acceptable for an object (of
any class) to have a method that returns an object that behaves
differently under core language concepts (like boolean evaluation)? I
would say "yes".

So, what other reasons exist for wanting to do away with nil.to_i? The
main (only other?) argument seems to be, "nil is special, and I want
to know for sure when I get a nil value. It's so special, I should get
a NoMethodError if I try to do (just about) anything to it."

I agree that it's special. I've certainly seen that foo.id => 4 (when
foo is unexpectedly nil) can cause confusion.

However, which of the following is 'better'?

# Assume nil.to_i is not available
def foo( bar, jim )
bar = 0 if bar.nil? # explicit setting
a = bar.to_i * 2
b = jim.to_i * 2 # I want it to blow up if jim is nil
end

# Assume nil.to_i is available
def foo( bar, jim )
a = bar.to_i * 2 # Magically treat nil as zero

raise "Jim can't be nil!" if jim.nil?
b = jim.to_i * 2
end

If the fitness criterion for 'better' in this case is 'less lines of
code', then it depends on which case is more prevalent. If the fitness
criterion is instead 'safer', then not having to_i seems to make sense
to me. If the fitness criterion is 'more convenient' or 'more
expected', then having to_i makes sense to those for whom 0 is a
reasonable integer representation of nil.

If I were to advocate removing nil.to_i, I would probably advocate
removing nil.to_s for the same reasons...and then I would really,
really hate life in the Rails world (and in other string interpolation
areas). For that reason alone I can't personally vote for getting rid
of nil.to_i.
 
C

Chad Perrin

nil has other uses besides representing nothing: it means false in a
boolean context.

What purpose do you propose for nil if it isn't differentiated in
behavior from false in that manner? Shouldn't we then either replace all
instance of false with nil or all instances of nil with false?

If nil
Under that logic then zero must evaluate to false, just like C and Python does.
I don't agree with that, of course.

No . . . 0 would evaluate as 0 or true, while nil would evaluate as
false. Similarly, "1" evaluates as "1", but "1".to_i evaluates as 1.
That's the point of a method like to_i, as far as I can tell.

I'd expect the same behavior as FalseClass and TrueClass: undefined method.

Thanks for clarifying that. That makes a certain amount of sense, though
I'm not convinced it makes more sense than nil.to_i returning 0.

Because if I want 0 would expect or send 0, not nil.to_i.
Because it doesn't make sense to me that nil, which means false also,
can be represented as zero, when zero doesn't mean false, but true.

Trans made the point that eliminating to_i from the nil lineup of methods
would suddenly result in a lot of ( x ? x.to_i : 0 ) being used. It
seems to me that nil.to_i is convenient, makes a certain amount of
logical sense, and doesn't actually introduce unexpected behavior except
in pathological edge-cases. Am I missing some non-pathological, non-edge
cases?

I don't think I understood you. Correct me plese, but I think you're talking
about an accumulator? In that case, you should start from zero, not nil.

. .
 

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,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top