Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Object#to_b

0 views
Skip to first unread message

Daniel Schierbeck

unread,
Nov 16, 2005, 4:32:15 PM11/16/05
to
Currently, as far as I know, `if' and `unless' merely check if an object
is of either types NilClass or FalseClass. This seems to contradict the
duck-typing paradigm. I propose that we implement a method Object#to_b
that is called by `if' and `unless'. It should return a boolean value.
That way, a developer can decide whether or not an object should
evaluate to true or false.

class Connection
def open?; end
def closed?; end
def to_b; open?; end
end

connection = Connection.new(...)
if connection
# ...
end

Implementation:

class Object
def to_b
true
end
end

class FalseClass
def to_b
false
end
end

class NilClass
def to_b
false
end
end


One problem I see with this proposal is that it seems like a lot of
people check if a variable has been set by writing `if var ...'. This
change would require that people wrote `unless var.nil?', which I
personally find more correct as well.


Cheers,
Daniel

Austin Ziegler

unread,
Nov 16, 2005, 4:50:24 PM11/16/05
to
On 11/16/05, Daniel Schierbeck <daniel.s...@gmail.com> wrote:
> Currently, as far as I know, `if' and `unless' merely check if an object
> is of either types NilClass or FalseClass. This seems to contradict the
> duck-typing paradigm. I propose that we implement a method Object#to_b
> that is called by `if' and `unless'. It should return a boolean value.
> That way, a developer can decide whether or not an object should
> evaluate to true or false.

> One problem I see with this proposal is that it seems like a lot of


> people check if a variable has been set by writing `if var ...'. This
> change would require that people wrote `unless var.nil?', which I
> personally find more correct as well.

This would break a lot of my code, personally. I used to use "unless
var.nil?" but it is easier to say:

if var and var.foo

than:

if (not var.nil?) and var.foo

I'm not *quite* sure what the "unless" version of the test would be:

unless var.nil? or var.foo.nil?

Not quite what I want. I think that #to_b would be problematic,
especially in the example that you gave, since it's more expressive to
say:

if conn.open?

than:

if conn

which implies you're checking to see if conn is really there.

-austin
--
Austin Ziegler * halos...@gmail.com
* Alternate: aus...@halostatue.ca


Eric Mahurin

unread,
Nov 16, 2005, 4:54:17 PM11/16/05
to
On 11/16/05, Daniel Schierbeck <daniel.s...@gmail.com> wrote:
> Currently, as far as I know, `if' and `unless' merely check if an object
> is of either types NilClass or FalseClass. This seems to contradict the
> duck-typing paradigm. I propose that we implement a method Object#to_b
> that is called by `if' and `unless'.It should return a boolean value.

> That way, a developer can decide whether or not an object should
> evaluate to true or false.

You could also ask that "and", "or", "not", "!", "||", "&&" be
operator methods. I think the reason all of this is built-in is
performance. All of this stuff doesn't have to go through the normal
method-call mechanism. If you do a benchmark on "unless x" vs. "if
x.nil?" you'll see the difference.


Daniel Sheppard

unread,
Nov 16, 2005, 7:48:18 PM11/16/05
to
The actual need for an Object#to_b is that there's no way to make your
own custom object that will behave in a false/nil manner.

I can't think of a usecase where I'd want to put extra information into
a nil/false object instead of using exceptions, but maybe one of those
people that keep asking about subclassing FalseClass and NilClass can
explain their use-cases.

Unless somebody can come up with a decent use-case, I'd say that we just
change the if evaluations to also allow subclasses of FalseClass and
NilClass (which will all be just singletons as they don't have new). Or
change if to look at nil? to determine whether it's true or not.

> -----Original Message-----
> From: Austin Ziegler [mailto:halos...@gmail.com]
> Sent: Thursday, 17 November 2005 8:50 AM
> To: ruby-talk ML
> Subject: Re: Object#to_b
>
> On 11/16/05, Daniel Schierbeck <daniel.s...@gmail.com> wrote:
> > Currently, as far as I know, `if' and `unless' merely check if an
> > object is of either types NilClass or FalseClass. This seems to
> > contradict the duck-typing paradigm. I propose that we implement a
> > method Object#to_b that is called by `if' and `unless'. It
> should return a boolean value.
> > That way, a developer can decide whether or not an object should
> > evaluate to true or false.
>

> > One problem I see with this proposal is that it seems like a lot of
> > people check if a variable has been set by writing `if var
> ...'. This
> > change would require that people wrote `unless var.nil?', which I
> > personally find more correct as well.
>
> This would break a lot of my code, personally. I used to use
> "unless var.nil?" but it is easier to say:
>
> if var and var.foo
>
> than:
>
> if (not var.nil?) and var.foo
>
> I'm not *quite* sure what the "unless" version of the test would be:
>
> unless var.nil? or var.foo.nil?
>
> Not quite what I want. I think that #to_b would be
> problematic, especially in the example that you gave, since
> it's more expressive to
> say:
>
> if conn.open?
>
> than:
>
> if conn
>
> which implies you're checking to see if conn is really there.
>
> -austin
> --
> Austin Ziegler * halos...@gmail.com
> * Alternate: aus...@halostatue.ca
>
>
>

#####################################################################################
This email has been scanned by MailMarshal, an email content filter.
#####################################################################################


Daniel Sheppard

unread,
Nov 16, 2005, 7:50:39 PM11/16/05
to
> Unless somebody can come up with a decent use-case, I'd say
> that we just change the if evaluations to also allow
> subclasses of FalseClass and NilClass (which will all be just
> singletons as they don't have new). Or change if to look at
> nil? to determine whether it's true or not.

That was meant to be "If somebody can..."

Unless, or course the use-cases present a stronger case for to_b.

Jeremy Kemper

unread,
Nov 16, 2005, 8:10:45 PM11/16/05
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Nov 16, 2005, at 4:48 PM, Daniel Sheppard wrote:
> The actual need for an Object#to_b is that there's no way to make your
> own custom object that will behave in a false/nil manner.
>
> I can't think of a usecase where I'd want to put extra information
> into
> a nil/false object instead of using exceptions, but maybe one of those
> people that keep asking about subclassing FalseClass and NilClass can
> explain their use-cases.
>
> Unless somebody can come up with a decent use-case, I'd say that we
> just
> change the if evaluations to also allow subclasses of FalseClass and
> NilClass (which will all be just singletons as they don't have
> new). Or
> change if to look at nil? to determine whether it's true or not.

In Active Record:

class Foo < ActiveRecord::Base
has_one :bar
end

I want a simple test for presence of bar, so return nil from
Foo#bar if there is no associated object:

if foo.bar
# ...
end

I also want to treat Foo#bar as a reflection of the association
so I can have meta-methods for querying the column type, creating
objects, performing scoped queries, etc:

puts foo.bar.column_type
foo.bar.create(:name => 'first bar')

This usage feels very expressive and is possible for one-to-many
and many-to-many associations because acting like an Array is not
a problem. But for one-to-one associations, we must act like nil,
which is impossible due to RTEST doing direct object comparison.

to_b is one way to do it, but I think it is too disruptive.
I would prefer to define #nil? and have RTEST call it.

Best,
jeremy
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (Darwin)

iD8DBQFDe9iQAQHALep9HFYRArk3AJ4/tPb3QTnptm5LGFL2+s9MJlO5BgCeOGZH
DHvBGN0h+pD/ReEtk9kcjLk=
=TB0L
-----END PGP SIGNATURE-----


Yukihiro Matsumoto

unread,
Nov 16, 2005, 8:11:12 PM11/16/05
to
Hi,

In message "Re: Object#to_b"


on Thu, 17 Nov 2005 09:48:18 +0900, "Daniel Sheppard" <dan...@pronto.com.au> writes:

|The actual need for an Object#to_b is that there's no way to make your
|own custom object that will behave in a false/nil manner.

Yes. And I believe it's good. There's no possibility for us to
confuse whether something is false. false is false, nil is false,
that's all.

In general, such attempt to define new false values is not worth the
performance cost we all have to pay.

matz.


Austin Ziegler

unread,
Nov 16, 2005, 8:22:35 PM11/16/05
to
On 11/16/05, Daniel Sheppard <dan...@pronto.com.au> wrote:
> The actual need for an Object#to_b is that there's no way to make your
> own custom object that will behave in a false/nil manner.

I don't know that this is a good or useful thing. I think that it would
decrease the overall clarity of Ruby code.

> I can't think of a usecase where I'd want to put extra information
> into a nil/false object instead of using exceptions, but maybe one of
> those people that keep asking about subclassing FalseClass and
> NilClass can explain their use-cases.

And I think that if they do, they'll be directed to different possible
solutions.

> Unless somebody can come up with a decent use-case, I'd say that we
> just change the if evaluations to also allow subclasses of FalseClass
> and NilClass (which will all be just singletons as they don't have
> new). Or change if to look at nil? to determine whether it's true or
> not.

Hm. No, I don't think that either is good. I would suggest that neither
FalseClass nor NilClass should meaningfully have subclasses and that if
should *not* look at #nil?. I don't think that there is a good case to be found
for this at all.

Jeremy Kemper

unread,
Nov 16, 2005, 8:25:03 PM11/16/05
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Nov 16, 2005, at 5:11 PM, Yukihiro Matsumoto wrote:
> In message "Re: Object#to_b"
> on Thu, 17 Nov 2005 09:48:18 +0900, "Daniel Sheppard"
> <dan...@pronto.com.au> writes:
>
> |The actual need for an Object#to_b is that there's no way to make
> your
> |own custom object that will behave in a false/nil manner.
>
> Yes. And I believe it's good. There's no possibility for us to
> confuse whether something is false. false is false, nil is false,
> that's all.

I agree; I have always liked this behavior.


> In general, such attempt to define new false values is not worth the
> performance cost we all have to pay.

I would not like new false values, but I would like to be able to proxy
the existing false values. Especially nil.

What is the cost?

Best,
jeremy
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (Darwin)

iD8DBQFDe9vrAQHALep9HFYRAje9AKDR7d9/ej5+JwGYxDfBiH7zxBlDZwCgzUg0
Z61NdDino/WTrg4sz1CrMEY=
=apF5
-----END PGP SIGNATURE-----


Mauricio Fernández

unread,
Nov 16, 2005, 9:00:18 PM11/16/05
to
On Thu, Nov 17, 2005 at 10:25:03AM +0900, Jeremy Kemper wrote:
> On Nov 16, 2005, at 5:11 PM, Yukihiro Matsumoto wrote:
> >In general, such attempt to define new false values is not worth the
> >performance cost we all have to pay.
>
> I would not like new false values, but I would like to be able to proxy
> the existing false values. Especially nil.
>
> What is the cost?

A full method dispatch instead of an inlined test

#define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)

--
Mauricio Fernandez


Joel VanderWerf

unread,
Nov 16, 2005, 11:14:58 PM11/16/05
to

.. or Object#not_to_b, that is the question.

I'm already sorry I said that ;)

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Daniel Schierbeck

unread,
Nov 17, 2005, 9:44:00 AM11/17/05
to
Austin Ziegler wrote:
> I used to use "unless
> var.nil?" but it is easier to say:
>
> if var and var.foo
>
> than:
>
> if (not var.nil?) and var.foo

`if var and var.foo' would still work. If `var' is undefined (nil), its
#to_b method will return false. So unless var is an object that
overrides the #to_b method, your code will still work.

I can see the problem with the performance Matz brought up, but this was
more meant as a philosophical discussion (though I can see now that I
was quite concrete.) It actually came in response to the whole
"subclassing FalseClass and NilClass" discussion, where I believe the
#to_b method would be more true to the idea of duck-typing.


Cheers,
Daniel

Daniel Schierbeck

unread,
Nov 17, 2005, 9:47:03 AM11/17/05
to
Joel VanderWerf wrote:
> .. or Object#not_to_b, that is the question.
>
> I'm already sorry I said that ;)
>

class Foo
def to_b; end
def bar
if to_b or not to_b
# ...
end
end
end

:)

men...@rydia.net

unread,
Nov 17, 2005, 9:49:42 AM11/17/05
to
Quoting Jeremy Kemper <jer...@bitsweat.net>:

> I would not like new false values, but I would like to be able to
> proxy the existing false values. Especially nil.

Ah, fudge. I hadn't thought of that. That is one place where
lazy.rb falls down.

promise { false } will always be true :/

(unless you use an explicitly force()'d value.)

> What is the cost [of allowing NilClass and FalseClass subclasses]?

I don't see any way that it could be as efficient as the current
setup, where nil and false are immediate values and are checked
with a simple bitmask.

-mental


Trans

unread,
Nov 17, 2005, 10:07:24 AM11/17/05
to
> I don't see any way that it could be as efficient as the current
> setup, where nil and false are immediate values and are checked
> with a simple bitmask.

Could they get special object_id's that are easy to check?

T.

men...@rydia.net

unread,
Nov 17, 2005, 10:40:08 AM11/17/05
to
Quoting Trans <tran...@gmail.com>:

Like...?

Currently, for 32-bit systems:

false: 00000000000000000000000000000000
true: 00000000000000000000000000000010
nil: 00000000000000000000000000000100
undef: 00000000000000000000000000000110
Symbol: XXXXXXXXXXXXXXXXXXXXXXXX00001110
Object reference: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0
Fixnum: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX1

That means we get 24 bits worth of symbols, 31 (signed) bits of
fixnums, and 31-bit pointers to objects (so objects must be aligned
on two-byte boundaries).

-mental


daz

unread,
Nov 17, 2005, 12:06:03 PM11/17/05
to

Joel VanderWerf wrote:
>
> .. or Object#not_to_b, that is the question.
>
> I'm already sorry I said that ;)
>

With good reason ;)

class Object; def to_b; !!self; end; end
alias that? to_b

that? #-> true


daz

Jeremy Kemper

unread,
Nov 17, 2005, 3:04:30 PM11/17/05
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Right: I had to dig as far as RTEST when I tried to act like nil
to understand why it did not work. I was happy to see that it's
very fast but was unhappy to discover the "line in the sand" between
dynamic, expressive Ruby and its concern for raw performance.

There is a Moore's law for one but not the other.

Has anyone measured the cost of doing boolean tests the Ruby way?
Clearly it will be much slower as a microbenchmark, but perhaps the
overall cost for most Ruby programs is low enough to tip the balance.

And if not now, perhaps in one year.

jeremy
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (Darwin)

iD8DBQFDfOJJAQHALep9HFYRAjZyAJ42wnfNTnsiqM0E4TFNzaoVITT7AwCffZp0
ONJn0imCyJI3g0CR7l+A3PA=
=TSa9
-----END PGP SIGNATURE-----


gwt...@mac.com

unread,
Nov 17, 2005, 4:26:51 PM11/17/05
to

On Nov 17, 2005, at 3:04 PM, Jeremy Kemper wrote:
> Right: I had to dig as far as RTEST when I tried to act like nil
> to understand why it did not work. I was happy to see that it's
> very fast but was unhappy to discover the "line in the sand" between
> dynamic, expressive Ruby and its concern for raw performance.

I think one of the interesting/useful features of Ruby is its
handling of boolean values. In thinking about the original post,
I came across a nice discussion of nil, null, and false in object
oriented languages, in particular Smalltalk and Objective-C.

http://www.smalltalkchronicles.net/edition2-1/null_object_pattern.htm

I really like the null object pattern but I'm not sure I'm ready
to fully embrace it with a generalized null object and even then I'm
not sure how I think that should fit with nil/false.

My hunch is that either you have a generalized null object that is
considered false or you don't have it. The idea of having user-defined
false objects just seems to be a opening a Pandora's box of issues.

Gary Wright

0 new messages