Zero is true ... whoda thunk?

In article 2h1dfjF7uummU1@uni-berlin.de,

“Michael Geary” Mike@DeleteThis.Geary.com wrote in message
news:10allar4vlk2092@corp.supernews.com

what makes zero
so special that it would warrant being false?

Because in the real world, zero means false.

Suppose you have zero quarts of milk in your refrigerator. I am visiting
and
I ask: Got milk?

I just wanted to note that I agree with you 100% and find any other
interpretation baffling. This is a common error for me - 99% of my Ruby
programming errors stem from runtime NoMethodErrors on nil because of Ruby’s
failure to correctly interpret some boundary condition. If numbers always
evaluate to true, it seems absurd to allow them to be used in conditionals
predicating on truth - we should at least get a good diagnostic, IMHO.
Arguments about the elegance or uniformity of zero’s truth are pretty weak
in my opinion, due to the fact that Ruby does not exist in a
vacuum.

_ I think this issue is a Licorice Test[1] for Ruby. To me it’s
fundamental to the entire point of Ruby. If you are really
bothered by this, then maybe Ruby is not for you. For me, its
one of the big reasons I really like Ruby. A Ruby in which
zero was false would not be Ruby…

LOTS
of external libraries, extensions, interfaces, etc, implicitly and
explicitly require zero to be false.

_ To me one of the joys of Ruby is that it largely hides the
short sited hardware dependent idiosycrancies of underlying
implementations.

_ Booker C. Bense

[1]- Either you really like it or you hate it…

···

Mary M. Inuet <maryinuet@ya_hoo.com> wrote:

“Mary M. Inuet” <maryinuet@ya_hoo.com> wrote in message news:2h1dfjF7uummU1@uni-berlin.de

“Michael Geary” Mike@DeleteThis.Geary.com wrote in message
news:10allar4vlk2092@corp.supernews.com

what makes zero
so special that it would warrant being false?

Because in the real world, zero means false.
[…]
failure to correctly interpret some boundary condition. If numbers always
evaluate to true, it seems absurd to allow them to be used in conditionals
predicating on truth - we should at least get a good diagnostic, IMHO.
Arguments about the elegance or uniformity of zero’s truth are pretty weak
in my opinion, due to the fact that Ruby does not exist in a vacuum. LOTS
of external libraries, extensions, interfaces, etc, implicitly and
explicitly require zero to be false.

I agree that if numbers are always evaluated to true, it’s better
for Ruby to warn the use of numbers as predicates. (“Absurd” is a
bit too strong a word, in my opinion.)

But, I don’t agree with the practical universality of zero as false.
If you think that zero is almost always treated as false in
practice, I guess that’s because of your “culture” (perhaps related
to the C language and cousins). When I began programming in the Bourn
shell (/bin/sh), I was surprised that the return value of zero
is treated as true in predicates, as in

if grep -s hello file.txt; then ...

grep returns zero when it finds a match. Almost all standard Unix
tools return zero to mean “success” and/or “true”. . . . What’s the
moral? It’s best to keep truthness and numbers separate. Also, I
don’t buy the argument that since “LOTS” of libraries uses the
zero-as-false convention, Ruby should follow the suit. I would
argue that in LOTS of other contexts zero is treated as the signal
of “true”. (Another example is, as someone mentioned, some assembly
languages have instructions which say “jump if such
and such flag is zero”.)

Jamis Buck jgb3@email.byu.edu writes:

I’m SO glad that Ruby forces you to compare numbers explicitly, instead
of implicitly converting to bool. It makes code that much more readable.

It doesn’t, though. This code will always print “foo”:
a = SomethingReturningANumber()
if (a) # Probably meant to say “a != 0”, or maybe “a == 0”
puts “foo”
end
I think it should force you to compare numbers explicitly – comparisons
should raise exceptions if passed anything other than booleans. But it’s
too late for such a change.

···


Steven
“No egg nog! In fact, no nog, period!”

Booker C. Bense wrote:

_ I think this issue is a Licorice Test[1] for Ruby. To me it’s
fundamental to the entire point of Ruby. If you are really
bothered by this, then maybe Ruby is not for you. For me, its
one of the big reasons I really like Ruby. A Ruby in which
zero was false would not be Ruby…

Agreed.

Boolean values are used for what? To test a condition. A normal condition like
“x > 0” or “s.empty?” has a value of true or false. I think there’s no
discussion about this.

Besides those normal conditions Ruby has a shortcut for exactly one special
case: “did I get a valid result from a method call or not?” In Ruby, this
translates to “did I get a real object or nil?” (Of course nil is an object as
everything else in Ruby, but it has the meaning of “no object”.)

You could code this condition as

 if !x.nil?

or
unless x.nil?

but since it is so common, Ruby has the shortcut

 if x

From this point of view, only nil can be treated as false.

Regards,
Pit

Steven@ruby-lang.org wrote:

Jamis Buck jgb3@email.byu.edu writes:

I’m SO glad that Ruby forces you to compare numbers explicitly, instead
of implicitly converting to bool. It makes code that much more readable.

It doesn’t, though. This code will always print “foo”:
a = SomethingReturningANumber()
if (a) # Probably meant to say “a != 0”, or maybe “a == 0”
puts “foo”
end
I think it should force you to compare numbers explicitly – comparisons
should raise exceptions if passed anything other than booleans. But it’s
too late for such a change.

Steven
“No egg nog! In fact, no nog, period!”

Sorry – I mispoke. My “force” I meant that Ruby requires you to do
explicit numeric comparisons for your conditions to work correctly, not
that it actually enforces that programming practice. You’re right,
though. It would be nice if Ruby enforced that.

···


Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis

ruby -h | ruby -e
‘a=;readlines.join.scan(/-(.)[e|Kk(\S*)|le.l(…)e|#!(\S*)/) {|r| a <<
r.compact.first };puts “\n>#{a.join(%q/ /)}<\n\n”’

Hi –

Pit Capitain pit@capitain.de writes:

Booker C. Bense wrote:

_ I think this issue is a Licorice Test[1] for Ruby. To me it’s
fundamental to the entire point of Ruby. If you are really
bothered by this, then maybe Ruby is not for you. For me, its
one of the big reasons I really like Ruby. A Ruby in which
zero was false would not be Ruby…

Agreed.

Boolean values are used for what? To test a condition. A normal
condition like “x > 0” or “s.empty?” has a value of true or false. I
think there’s no discussion about this.

Besides those normal conditions Ruby has a shortcut for exactly one
special case: “did I get a valid result from a method call or not?”
In Ruby, this translates to “did I get a real object or nil?” (Of
course nil is an object as everything else in Ruby, but it has the
meaning of “no object”.)

You could code this condition as

 if !x.nil?

or
unless x.nil?

but since it is so common, Ruby has the shortcut

 if x

From this point of view, only nil can be treated as false.

I’m not sure about these equivalencies, though. “if x” is not the
same as “if !x.nil?”, since they’ll give different results if x is
(the object) false. (I think that’s part of why #nil? exists.) Also,
in a case like Regexp#match, which returns nil on no-match, you’re
definitely getting a valid result (no match). And nil as a method
return is not a Ruby-wide way of signaling failure; for example,
Enumerable#select returns an empty array when it selects nothing. (I
guess an empty MatchData object would be kind of paradoxical, since it
should be a NoMatchData object.)

(None of which bears directly on zero – I’m just chattering :slight_smile:

David

···


David A. Black
dblack@wobblini.net

If the sematic meaning of if (object) is existence or non-existance
(non-nil or nil) then doing this would be inelegant. Numbers are
objects, after all, and should ideally follow the same conventions.

One might argue that only boolean expressoins be allowed in control
statements, but I like the current mechanism and don’t see too many
shortcomings.

Nick

Steven@ruby-lang.org wrote:

···

Jamis Buck jgb3@email.byu.edu writes:

I’m SO glad that Ruby forces you to compare numbers explicitly, instead
of implicitly converting to bool. It makes code that much more readable.

It doesn’t, though. This code will always print “foo”:
a = SomethingReturningANumber()
if (a) # Probably meant to say “a != 0”, or maybe “a == 0”
puts “foo”
end
I think it should force you to compare numbers explicitly – comparisons
should raise exceptions if passed anything other than booleans. But it’s
too late for such a change.

Steven
“No egg nog! In fact, no nog, period!”

Jamis Buck wrote:

Jamis Buck jgb3@email.byu.edu writes:

I’m SO glad that Ruby forces you to compare numbers explicitly,
instead of implicitly converting to bool. It makes code that much
more readable.

It doesn’t, though. This code will always print “foo”:
a = SomethingReturningANumber()
if (a) # Probably meant to say “a != 0”, or maybe “a == 0”
puts “foo”
end
I think it should force you to compare numbers explicitly –
comparisons
should raise exceptions if passed anything other than booleans. But
it’s
too late for such a change.

Steven

“No egg nog! In fact, no nog, period!”

Sorry – I mispoke. My “force” I meant that Ruby requires you to do
explicit numeric comparisons for your conditions to work correctly,
not that it actually enforces that programming practice. You’re right,
though. It would be nice if Ruby enforced that.

The problem with this there are a number of methods which return a
numeric value of true and nil for false.

e.g. the =~ operator returns the position of the substring that matches
the regexp, or nil if it fails to match. If either you disallowed
numeric values, or made zero a false value, in a boolean context then
this behaviour would have to change to allow

if(/abc/ =~ “abc”)

end

···

Steven@ruby-lang.org wrote:


Mark Sparshatt

David Alan Black wrote:

Pit Capitain pit@capitain.de writes:

A normal
condition like “x > 0” or “s.empty?” has a value of true or false. I
think there’s no discussion about this.

Besides those normal conditions Ruby has a shortcut for exactly one
special case: “did I get a valid result from a method call or not?”
In Ruby, this translates to “did I get a real object or nil?”

I’m not sure about these equivalencies, though. “if x” is not the
same as “if !x.nil?”, since they’ll give different results if x is
(the object) false.

That’s why I made the distinction between testing “normal conditions” (true /
false) and testing the outcome of a method (valid object / no object). I counted
predicates (boolean methods) like nil?, zero?, empty? as “normal conditions” to
be tested with the true / false semantics. The “valid object / no object”
semantics don’t make sense for predicates.

Also,
in a case like Regexp#match, which returns nil on no-match, you’re
definitely getting a valid result (no match). And nil as a method
return is not a Ruby-wide way of signaling failure; for example,
Enumerable#select returns an empty array when it selects nothing. (I
guess an empty MatchData object would be kind of paradoxical, since it
should be a NoMatchData object.)

Maybe I didn’t find the right words. Of course returning nil from a method is
“valid” in the sense of “it is no exception”. For example, I read the match
method as “give me a match” and the result nil as “sorry, I can’t”. As you said,
you can’t reasonably return a match object for “no match”.

On the other hand, select alias find_all to me means “give me a list of all
elements that…”. Even if there are no such elements, the method returns a
list. It is empty, but it is a list, a valid result. Because select always
returns a valid result, it doesn’t make sense to interpret this result as a
condition.

If you wanted to make a boolean test (whether there exist matching elements or
not), you wouldn’t use select aka find_all, but find. Here it makes sense to ask
“did you really find something?”, and here again the result nil means “no, I
didn’t”. (If you’re only interested in the test result and not in an actual
matching element, you could use the predicate any?, which would show the
intention even better.)

To summarize in other words: there are the obvious tests for boolean conditions
including predicates (true / false) and an implicit test for success / no
success (not-nil / nil).

Does this make more sense? Maybe not, it’s 03:50 AM…

Regards,
Pit