Booleans

Okay, as a convert from Perl to Ruby, I have to say that I love
just about everything Ruby has to offer. Just about. I wish it had
better built-in support for Unicode, but that’s a minor quibble.
However, one thing I really don’t like is the handling of booleans.

I would be happy if the conditionals required actual Boolean
(i.e., TrueClass or FalseClass) objects and complained otherwise, even
though it’s rather different from the typeless nature of the rest
of Ruby.

I would also be happy if the test for falseness was less simplistic than
"false is false, nil is false, everything else is true". I am constantly
being bitten by the fact that 0 is true.

Ideally, what I’d like to see is the ability for each class to decide what
constitutes true and false for objects of that class - for instance, a
to_b method, by analogy with to_s. Then you just need three method
definitions:

class Object; def to_b() true end end 
class FalseClass; def to_b() false end end 
class NilClass; def to_b() false end end 

And boom, you have the current behavior and the ability to extend it.
For instance, if you prefer that zero be false, you can do

class Numeric; def to_b() self != 0 end end

Admittedly, this would break the semantics of =~ etc, but you could
fix that with a new class for match results that still has 0 as true:

class Index < Fixnum; def to_b() true end end 

Similar methods would allow empty strings and collections to return
false, etc. The point is that it would gain a lot of flexibility.
And a static method like this:

def TrueClass.strictlyTrue?(x) x != nil && x != false end

would allow the user to override any given class’s definitions to
make sure that an object is “really” true.

Thoughts?

-Mark

What about not automagically converting everything to boolean?

Gergo

···

On 0715, Mark J. Reed wrote:

I would also be happy if the test for falseness was less simplistic than
“false is false, nil is false, everything else is true”. I am constantly
being bitten by the fact that 0 is true.

±[ Kontra, Gergelykgergely@mcl.hu PhD student Room IB113 ]---------+
http://www.mcl.hu/~kgergely “Olyan langesz vagyok, hogy |
Mobil:(+36 20) 356 9656 ICQ: 175564914 poroltoval kellene jarnom” |
±- Magyar php mirror es magyar php dokumentacio: http://hu.php.net --+

If you know that you will be getting a Fixnum in response, you can use Fixnum#nonzero? and Fixnum#zero? to get the tests that you’re after.

-austin

···

On Tue, 15 Jul 2003 05:34:02 +0900, Mark J. Reed wrote:

I would also be happy if the test for falseness was less simplistic
than “false is false, nil is false, everything else is true”. I am
constantly being bitten by the fact that 0 is true.


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.07.14
* 17:15:07

I would also be happy if the test for falseness was less simplistic than
“false is false, nil is false, everything else is true”. I am
constantly
being bitten by the fact that 0 is true.
What about not automagically converting everything to boolean?

Then the following nice feature would not be possible:

@var ||= SomeClass.new

···

----- Original Message -----
From: “KONTRA Gergely” kgergely@mlabdial.hit.bme.hu
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, July 14, 2003 1:45 PM
Subject: Re: Booleans

On 0715, Mark J. Reed wrote:

Gergo

±[ Kontra, Gergelykgergely@mcl.hu PhD student Room IB113 ]---------+

http://www.mcl.hu/~kgergely “Olyan langesz vagyok, hogy |
Mobil:(+36 20) 356 9656 ICQ: 175564914 poroltoval kellene jarnom” |
±- Magyar php mirror es magyar php dokumentacio: http://hu.php.net --+

Sure. Or just plain old != 0. But I always forget that I need to do
anything at all beyond “if (expression returning Numeric)”. After
20 years programming C and derivatives, I have simply internalized
that zero is SUPPOSED to be false, dagnabit!

But I do think it would be worthwhile to allow classes to specify
their own truth values, even if Ruby as shipped doesn’t take advantage
of this feature.

-Mark

···

On Tue, Jul 15, 2003 at 06:17:46AM +0900, Austin Ziegler wrote:

On Tue, 15 Jul 2003 05:34:02 +0900, Mark J. Reed wrote:

?I would also be happy if the test for falseness was less simplistic
?than “false is false, nil is false, everything else is true”. ?I am
?constantly being bitten by the fact that 0 is true.

If you know that you will be getting a Fixnum in response,
you can use Fixnum#nonzero? and Fixnum#zero? to get the tests that
you’re after.

I don’t think the issue is that it is difficult to come up with a test to
determine whether or not a number is zero or nonzero, it’s just whether
Ruby’s treatment of “false” and “nil” as false and 0 and the empty string as
true makes sense, or if it should maybe be more flexible.

I happen to like 0 and “” being logically “true”. It sometimes requires extra
typing but that’s fine. It’s very lisp-ey in that only nil is false,
everything else is true, only Ruby does have boolean classes, and in that
case the literal “false” should of course be false.

While I also kind-of like the idea of a “to_b” method that can determine if a
class is logically false, I see it causing lots of problems. If that were
possible, someone might take advantage of Ruby’s flexibility to make 0.to_b
be false for their program. This could lead to some real difficulty in
understanding or running other people’s code.

I prefer to be overly anal about the whole thing and always just say:
if 0 != retval …

Ben

···

On Mon July 14 2003 5:17 pm, Austin Ziegler wrote:

On Tue, 15 Jul 2003 05:34:02 +0900, Mark J. Reed wrote:

I would also be happy if the test for falseness was less simplistic
than “false is false, nil is false, everything else is true”. I am
constantly being bitten by the fact that 0 is true.

If you know that you will be getting a Fixnum in response, you can use
Fixnum#nonzero? and Fixnum#zero? to get the tests that you’re after.

“Mark J. Reed” markjreed@mail.com wrote in message news:20030714214600.GB23895@mulan.thereeds.org

···

On Tue, Jul 15, 2003 at 06:17:46AM +0900, Austin Ziegler wrote:

On Tue, 15 Jul 2003 05:34:02 +0900, Mark J. Reed wrote:

?I would also be happy if the test for falseness was less simplistic
?than “false is false, nil is false, everything else is true”. ?I am
?constantly being bitten by the fact that 0 is true.

If you know that you will be getting a Fixnum in response,
you can use Fixnum#nonzero? and Fixnum#zero? to get the tests that
you’re after.

Sure. Or just plain old != 0. But I always forget that I need to do
anything at all beyond “if (expression returning Numeric)”. After
20 years programming C and derivatives, I have simply internalized
that zero is SUPPOSED to be false, dagnabit!

But I do think it would be worthwhile to allow classes to specify
their own truth values, even if Ruby as shipped doesn’t take advantage
of this feature.

-Mark

That was part of the reason I submitted RCR #143 (on RubyGarden)
which, unfortunately, was rejected. Care to revive it?

Dan

I am constantly being bitten by the fact that 0 is true.

How about this : all non-nil objects are true, with the exception of
instances of FalseClass.

The same issues come up in SQL, where not only is a numeric 0 non-nil,
but so is zero-length string.

“Mark J. Reed” markjreed@mail.com wrote in message
news:20030714214600.GB23895@mulan.thereeds.org

···

On Tue, Jul 15, 2003 at 06:17:46AM +0900, Austin Ziegler wrote:

On Tue, 15 Jul 2003 05:34:02 +0900, Mark J. Reed wrote:

?I would also be happy if the test for falseness was less simplistic
?than “false is false, nil is false, everything else is true”. ?I am
?constantly being bitten by the fact that 0 is true.

If you know that you will be getting a Fixnum in response,
you can use Fixnum#nonzero? and Fixnum#zero? to get the tests that
you’re after.

Sure. Or just plain old != 0. But I always forget that I need to do
anything at all beyond “if (expression returning Numeric)”. After
20 years programming C and derivatives, I have simply internalized
that zero is SUPPOSED to be false, dagnabit!

But I do think it would be worthwhile to allow classes to specify
their own truth values, even if Ruby as shipped doesn’t take advantage
of this feature.

-Mark

While I also kind-of like the idea of a “to_b” method that can determine if a
class is logically false, I see it causing lots of problems. If that were
possible, someone might take advantage of Ruby’s flexibility to make 0.to_b
be false for their program. This could lead to some real difficulty in
understanding or running other people’s code.

You can already override parts of Ruby to cause plenty of odd
behaviour:

class Fixnum
def + (y)
1
end
end

puts “2 + 2 = #{2 + 2}”

I think Matz has commented on this topic before and said that the
reason that only nil and false are logically false is for performance.
The test for an object being nil or false is a very quick. If logical
tests instead had to call .to_b then that’d be an extra message send
on every if, and, or, when, …

– George

“George Marrows” george.marrows@ps.ge.com schrieb im Newsbeitrag
news:5e44d1a4.0307150201.7b1a6f08@posting.google.com

While I also kind-of like the idea of a “to_b” method that can
determine if a
class is logically false, I see it causing lots of problems. If that
were
possible, someone might take advantage of Ruby’s flexibility to make
0.to_b
be false for their program. This could lead to some real difficulty
in
understanding or running other people’s code.

You can already override parts of Ruby to cause plenty of odd
behaviour:

class Fixnum
def + (y)
1
end
end

puts “2 + 2 = #{2 + 2}”

That’s true, but why should we add another option to shoot ourselves in
the foot? I regard the to_b thing more serious than the changed operator

  • that you present: logical values always have to do with the way an
    algorithm executes, while a different return value for + is still a number
    and will only have minor impacts in most cases. Especially think of
    someone changing 0.to_b to return false and then using a module of someone
    else that relied on 0 being true…

I think Matz has commented on this topic before and said that the
reason that only nil and false are logically false is for performance.
The test for an object being nil or false is a very quick. If logical
tests instead had to call .to_b then that’d be an extra message send
on every if, and, or, when, …

That’s a serious reason, too.

Kind regards

robert

I am constantly being bitten by the fact that 0 is true.

How about this : all non-nil objects are true, with the exception of
instances of FalseClass.

Ok, see, I have absolutely no problem understanding the concept.
Easy as pie. I know that 0 is true, and I know why it is true.
But a couple decades of programming habits step in and write things
(like “if n” where I intended “if n==0”) on my behalf long before
my brain can step in and think “But what is Truth? Is Truth
unchanging law?”

Most of my non-Ruby programming these days is in Java, and I do the
same thing there, but at least the compiler catches it and yells at me.
:slight_smile:

The same issues come up in SQL, where not only is a numeric 0 non-nil,
but so is zero-length string.

Yeah, but that’s not the same issue. Since SQL is a declarative
language, I have never once mistaken it for C :-), and I do not
generally think of null database fields as equivalent to Boolean
“false”. Instead they are an entirely different beast which requires
things like NVL() (or COALESCE() or whatever your favorite RDBMS calls it);
I put nulls in the same general category as outer joins and such:
Ways To Deal With Data What Just Ain’t There.

Thanks, though.

-Mark

···

On Mon, Jul 14, 2003 at 08:23:48PM -0700, robert ehteshamzadeh wrote:

my brain can step in and think "But what is Truth? Is Truth
unchanging law?"

pigeon% perldoc perlfunc
[...]
       fcntl FILEHANDLE,FUNCTION,SCALAR
[...]

               You don't have to check for "defined" on the return from
               "fnctl". Like "ioctl", it maps a 0 return from the system call
               into "0 but true" in Perl.
                    ^^^^^^^^^^^^
[...]
pigeon%

Guy Decoux

Ok, see, I have absolutely no problem understanding the concept.
Easy as pie. I know that 0 is true, and I know why it is true.
But a couple decades of programming habits step in and write things
(like “if n” where I intended “if n==0”) on my behalf long before
my brain can step in and think “But what is Truth? Is Truth
unchanging law?”

Don’t forget to wash your hands… :wink:

Hal

···

----- Original Message -----
From: “Mark J. Reed” markjreed@mail.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, July 15, 2003 7:16 AM
Subject: Re: Booleans

Good point. Certain perl functions return “0E” when they mean “0”, so that
it can be treated as ‘true’.

Just remember that Ruby isn’t Perl or C. It doesn’t take long to get used to
it, and you’ll find it’s much cleaner. After all, why should the number “0”
be treated differently from the number “1”?

Regards,

Brian.

···

On Tue, Jul 15, 2003 at 09:25:08PM +0900, ts wrote:

my brain can step in and think “But what is Truth? Is Truth
unchanging law?”

pigeon% perldoc perlfunc
[…]
fcntl FILEHANDLE,FUNCTION,SCALAR
[…]

           You don't have to check for "defined" on the return from
           "fnctl".  Like "ioctl", it maps a 0 return from the system call
           into "0 but true" in Perl.
                ^^^^^^^^^^^^