Forum: Ruby Why 'if 0' succeeds in Ruby

Posted by Phlip (Guest)
on 2008-08-23 19:05
(Received via mailing list)
Rubiods:

One of the first "gotchas" here coming from another language is 0 is not 
like
'true'. This Daily WTF (which I think someone just posted here) 
illustrates the
problem which Ruby solves:

http://thedailywtf.com/Articles/pider-Detection.aspx

"Rather than check the difference between 0 and FALSE (or use a more 
appropriate
function), the original developer just dropped the first letter of each 
crawler
name so that strpos doesn't return 0."

     $spider_footprint = array('ooglebot', 'rawler', 'pider', 'ulliver',
                               'arvest', 'ahoo! Slurp');
     foreach($spider_footprint as $spider_name)
     {
        if (strpos($agent, $spider_name))
        {
           $is_spider = 1;
...

The problem is not that the programmer did not want to add FALSE != . 
The
problem is that language treats 0 as false, when 0 positively means we 
have a
good value with a 0 inside it.

0 as FALSE is a legacy of languages that could not distinguish 0 and 
NULL.

So the Ruby version would work like:

     if agent.index('googlebot')

So, once again, Ruby gives us the right defaults, precedents, and 
operations
that do much more, with much less code.
Posted by Dave Bass (dogsbody)
on 2008-08-23 19:35
But unfortunately Ruby regards both false and nil as not-true. For some 
reason, this is touted as a feature.

False and nil are two quite different concepts and should not be 
conflated.
Posted by Jason Roelofs (Guest)
on 2008-08-23 19:49
(Received via mailing list)
On Sat, Aug 23, 2008 at 1:31 PM, Dave Bass <davebass@musician.org> 
wrote:
> But unfortunately Ruby regards both false and nil as not-true. For some
> reason, this is touted as a feature.
>
> False and nil are two quite different concepts and should not be
> conflated.
> --
> Posted via http://www.ruby-forum.com/.
>
>

It's a perfectly fine feature and makes perfect sense if you
understand Ruby's object model. 0 is not nothing, it's Fixnum(0). Thus
it's an object, and not anything that can be differentiated from, say
2, 5 or "some string". Of course nil is NilClass and false is
FalseClass, which are also objects, but there needs to be something
that allows for if(false) checks, so those two classes are the special
cases. When taken as in context of Ruby as a whole, this of course
makes sense, as nil is effectively our nothing (like NULL / 0 in C and
C++) and FalseClass is our actual 'false'.

Jason
Posted by Phlip (Guest)
on 2008-08-23 20:30
(Received via mailing list)
Dave Bass wrote:

> But unfortunately Ruby regards both false and nil as not-true. For some 
> reason, this is touted as a feature.
>
> False and nil are two quite different concepts and should not be 
> conflated.

So the Ruby version would work like:

     if agent.index('googlebot')

So, once again, Ruby gives us the right defaults, precedents, and 
operations
that do much more, with much less code.

If you need false==, to self-document with more code, go for it. Given 
the
choice of forcing you to conflate 0, FALSE, and NULL, and only 
conflating
two of them, Ruby picked the right two, for nearly all situations. If 
you
want Pascal or Ada, you know where to get them!
Posted by David A. Black (Guest)
on 2008-08-23 20:40
(Received via mailing list)
HI --

On Sun, 24 Aug 2008, Dave Bass wrote:

> But unfortunately Ruby regards both false and nil as not-true. For some
> reason, this is touted as a feature.
>
> False and nil are two quite different concepts and should not be
> conflated.

They're not conflated, though. The two objects false and nil have in
common that they present as false, in the boolean sense, so that "if
false" and "if nil" both branch away. I think that's reasonable, since
otherwise you'd have to do a lot of "if (expr).nil? ||! expr" and
stuff like that. But they're still different objects, and the concepts
of falsehood and nilness are handled separately but converge at the
point of boolean value. The same is true of, say, the objects true and
"string".

It all comes down to the difference between being an object and having
a boolean "persona".


David
Posted by M. Edward (Ed) Borasky (Guest)
on 2008-08-24 03:40
(Received via mailing list)
On Sun, 2008-08-24 at 02:31 +0900, Dave Bass wrote:
> But unfortunately Ruby regards both false and nil as not-true. For some 
> reason, this is touted as a feature.
> 
> False and nil are two quite different concepts and should not be 
> conflated.

Exactly! To make matters worse, Lisp "traditionally" treated nil as
false, but Scheme has "true", "false" and "nil" and nil is treated as
true in Scheme.

So I don't have a problem with 0 not being false, but I do have a
problem with nil being false in Lisp and Ruby and true in Scheme. 0 is
0, nil is nil, true is true and false is false and that is that!

:)
--
M. Edward (Ed) Borasky
ruby-perspectives.blogspot.com

"A mathematician is a machine for turning coffee into theorems." --
Alfréd Rényi via Paul Erdős
Posted by Charles Oliver Nutter (Guest)
on 2008-08-24 04:19
(Received via mailing list)
M. Edward (Ed) Borasky wrote:
> 
> So I don't have a problem with 0 not being false, but I do have a
> problem with nil being false in Lisp and Ruby and true in Scheme. 0 is
> 0, nil is nil, true is true and false is false and that is that!

I tend to look at these things not from at the level of pedantic
consistency-mongering but in terms of what would be lost if the concept
were changed.

* a ||= x would no longer work, since unassigned a (nil) would not
evaluate to false causing x to be assigned.

* @a ||= x would no longer work

* a[n] ||= x would no longer work

* a.b ||= x would no longer work

"nil" being considered a boolean false seems absolutely natural to me,
and it makes possible a large number of concepts in Ruby we'd really 
miss.

- Charlie
Posted by David A. Black (Guest)
on 2008-08-24 04:31
(Received via mailing list)
Hi Ed --

On Sun, 24 Aug 2008, M. Edward (Ed) Borasky wrote:

>
> So I don't have a problem with 0 not being false, but I do have a
> problem with nil being false in Lisp and Ruby and true in Scheme. 0 is
> 0, nil is nil, true is true and false is false and that is that!
>
> :)

I understand what you're saying but I have a real, non-rhetorical
question: In practical terms, what do you think should be done about
such a situation? It seems to me that there are two possibilities:
either computer languages really do things differently, including
things like this (not just stylistic and/or cosmetic things), or they
don't and then they all become the same.

I can't think of a third possibility, and of course I like the first
better than the second :-)


David
Posted by Phlip (Guest)
on 2008-08-24 06:38
(Received via mailing list)
Charles Oliver Nutter wrote:

> * a ||= x would no longer work, since unassigned a (nil) would not 
> evaluate to false causing x to be assigned.
> 
> * @a ||= x would no longer work
> 
> * a[n] ||= x would no longer work
> 
> * a.b ||= x would no longer work

Exactly! a positively-written program should propagate value-objects, 
and
truths, as its booleans express. If you don't like that, then your code 
should
be more positive. Excess examples of 'if nil == q' or 'if false == q' 
are a sign
your program indulges in negativity.

So once again, a default Ruby behavior leads to better code style.
Posted by Hongli Lai (foobarwidget)
on 2008-08-24 11:27
Dave Bass wrote:
> But unfortunately Ruby regards both false and nil as not-true. For some 
> reason, this is touted as a feature.
> 
> False and nil are two quite different concepts and should not be 
> conflated.

I've found that treating both nil and false as false to be the correct 
behavior for most of my code. I've rarely written code where I *don't* 
want nil to be treated as false. Furthermore, in by far most of the use 
cases, I don't want to treat 0 as false.

In other languages, such as Perl, I end up having to write 'if 
(!defined($foo) || $foo eq "0")' all the time. So I like Ruby's 
behavior. Treating both nil and false as false covers most of the use 
cases.
Posted by Stefan Rusterholz (apeiros)
on 2008-08-24 12:10
Dave Bass wrote:
> But unfortunately Ruby regards both false and nil as not-true. For some 
> reason, this is touted as a feature.
> 
> False and nil are two quite different concepts and should not be 
> conflated.

They aren't conflated. nil != false in ruby, but nil and false have the 
same conditional value. Both are conditionally false. In my experience 
this has been the right call by matz all the way.

Regards
Stefan (apeiros)
Posted by Brian Marick (Guest)
on 2008-08-24 19:08
(Received via mailing list)
On Aug 23, 2008, at 8:35 PM, M. Edward (Ed) Borasky wrote:

> Exactly! To make matters worse, Lisp "traditionally" treated nil as
> false, but Scheme has "true", "false" and "nil" and nil is treated as
> true in Scheme.
>
> So I don't have a problem with 0 not being false, but I do have a
> problem with nil being false in Lisp and Ruby and true in Scheme. 0 is
> 0, nil is nil, true is true and false is false and that is that!


Back in my Common Lisp days, some Lisper (George Carrette, I think)
wrote about a dream he'd had. In it, he'd just written a fairly simple
piece of Lisp code when he realized Scheme's strictness was right. The
rest of the post was of the form:

  ... and then I realized that Scheme was right about X and my code
  had been taking advantage of Lisp's sloppiness. So I fixed that...

The punch line was that every "fix" made the code longer and more
complicated. It was brilliantly done, and I'm sad I've never been able
to find it.

One of the simplifications/complexifications was separating nil and
false.

-----
Brian Marick, independent consultant
Mostly on agile methods with a testing slant
www.exampler.com, www.exampler.com/blog, www.twitter.com/marick
Posted by Joost Diepenmaat (Guest)
on 2008-08-24 20:50
(Received via mailing list)
Brian Marick <marick@visibleworkings.com> writes:

> to find it.
http://www.aiai.ed.ac.uk/~jeff/random-text/T-lament

Cheers,
Joost.
Posted by matu (Guest)
on 2008-08-24 22:31
(Received via mailing list)
Dave Bass wrote:

> False and nil are two quite different concepts and should not be
> conflated.

I agree with you. I am also used to this. nil should never == true, and
neither be == false. Every comparison with nil should just fail.

if true
  p 'code is executed'
end

if false
  p 'code is not executed'
end

if nil
  p 'code is not executed'
end

unless nil
  p 'code is not executed'
end

if nil
  p 'code is not executed'
else
  p 'code is not executed'
end

But I actually like rubys behaviour as well: I somehow think it's 
logically
wrong, but practical.
Posted by Stefan Rusterholz (apeiros)
on 2008-08-24 22:45
matu wrote:
> Dave Bass wrote:
> 
>> False and nil are two quite different concepts and should not be
>> conflated.
> 
> I agree with you. I am also used to this. nil should never == true, and
> neither be == false. Every comparison with nil should just fail.

Well, I suggest you actually try the expression 'nil == false' in irb.
I think you'll be happy to see that it *is* false. Nil in ruby does NOT 
equal false.
As in my earlier post, it only is conditionally false, which is a whole 
different beast.

Regards
Stefan (apeiros)
Posted by Phlip (Guest)
on 2008-08-24 23:03
(Received via mailing list)
matu wrote:

>> False and nil are two quite different concepts and should not be
>> conflated.
> 
> I agree with you. I am also used to this. nil should never == true, and
> neither be == false. Every comparison with nil should just fail.

Code style should prefer the if condition to pass in positive and 
happy-path
situations. Further, the condition should also be stated positively.

You are asking to write extra code - if nil != my_object - for all of 
your
positive situations. Then, "nil not equal" is a double negative - nil 
and not.

However, Ruby is not stopping you from writing programmer-hostile code
everywhere. Go ahead and write the extra 'nil !=' if you must!

> But I actually like rubys behaviour as well: I somehow think it's logically
> wrong, but practical.

Sorry! (-:

Always remember anyone can write code that a compiler can read. It's a 
much
bigger challenge to write code a colleague can understand.
Posted by Phlip (Guest)
on 2008-08-24 23:04
(Received via mailing list)
Stefan Rusterholz wrote:
> equal false.
> As in my earlier post, it only is conditionally false, which is a whole 
> different beast.

And he covered that in his examples. He was using == false as a shortcut 
to say
"conditionally false".
Posted by matu (Guest)
on 2008-08-24 23:20
(Received via mailing list)
Phlip wrote:

> And he covered that in his examples. He was using == false as a shortcut
> to say "conditionally false".

thank you :)
Posted by Christopher Dicely (Guest)
on 2008-08-25 00:26
(Received via mailing list)
On Sun, Aug 24, 2008 at 1:26 PM, matu <m@t.u> wrote:
> Dave Bass wrote:
>
>> False and nil are two quite different concepts and should not be
>> conflated.
>
> I agree with you. I am also used to this. nil should never == true, and
> neither be == false. Every comparison with nil should just fail.

Every *comparison* with nil (except with itself) does fail.

"unless foo" is not a comparison of foo with false, it is exactly
equivalent to "if not foo".

You seem to be recommending an SQL-style 3-value logic which is
arguably useful in the context of SQL (though arguing that is a good
way to start a fight among different factions of database idealists),
but would, I think, have been a very bad choice for Ruby.

Ruby instead uses a two valued logic in which every expression must be
true or false in a boolean context. Given that, nil being false is the
only sensible answer. If you had to have it any other way, the only
even minimally acceptable way I can conceive would be nil being
*unacceptable* in a boolean context (such that it would raise an
exception if used in such a context), so you'd have to either do
exception trapping or explicitly test for nils. While it would
invalidate a lot of compact ruby idioms, you could argue that it would
be cleaner in some respects, and it avoids the three-value logic
problems.
Posted by Phlip (Guest)
on 2008-08-25 00:35
(Received via mailing list)
>> I agree with you. I am also used to this. nil should never == true, and
>> neither be == false. Every comparison with nil should just fail.
> 
> Every *comparison* with nil (except with itself) does fail.
> 
> "unless foo" is not a comparison of foo with false, it is exactly
> equivalent to "if not foo".
> 
> You seem to be recommending an SQL-style 3-value logic which is

For the second time so far: His statement is jargon, and is not to be 
taken
literally. His code sample showed what he meant!
Posted by Christopher Dicely (Guest)
on 2008-08-25 03:15
(Received via mailing list)
On Sun, Aug 24, 2008 at 3:30 PM, Phlip <phlip2005@gmail.com> wrote:
> For the second time so far: His statement is jargon, and is not to be taken
> literally. His code sample showed what he meant!

It wasn't "jargon", it was simply imprecise. But that's not the issue;
his code sample showed he wanted an SQL-style three-valued logic where
NULLs (nils) propagate, which is what I addressed in the message you
responded to.. If you read beyond the first two sentences, (even
through the portion you quoted of the third) you would have realized
that. You are doing the same thing (reading one piece of a message
without paying attention to the rest and criticizing based on that in
isolation) that you seem to be upset at others doing.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.