SimpleDelegator, nil, and truthiness

Hi there,

I've come across some code that has edge cases where nil is being passed
into a SimpleDelegator-based class.

So, something like `foo = SimpleDelegator.new(nil)`

This is weird, and I'm fixing it. But it uncovered something about how `if`
determines truthiness.

I would expect this code not to output anything, but it does:

foo = SimpleDelegator.new(nil)
puts "hi!" if foo

However, this code does not output anything:

foo = SimpleDelegator.new(nil)
puts "hi!" if !!foo

Are there any docs that describe this behaviour?

Thanks in advance!

Brent

Not an expert on this, but I think that the way that this works is that
while `foo = SimpleDelegator.new nil` shows as being `nil` and `foo == nil`
returns true, `foo.nil?` is `false` and `foo.class` returns
`SimpleDelegator` as its class. Furthermore, `foo.is_a? NilClass` returns
`false` whereas `nil.is_a? NilClass` returns `true` indicating to me that
Truthiness and Falsiness in Ruby are determined by whether or not something
is `FalseClass` or `NilClass`. Interestingly, this same behavior applies to
false, you can test it like this

This prints 'wut?'

fl = SimpleDelegator.new false
puts 'wut?' if fl

This prints nothing

fl = SimpleDelegator.new false
puts 'wut?' if !!fl

···

On Fri, Oct 20, 2017 at 9:36 AM, Brent Wheeldon <brent.wheeldon@gmail.com> wrote:

Hi there,

I've come across some code that has edge cases where nil is being passed
into a SimpleDelegator-based class.

So, something like `foo = SimpleDelegator.new(nil)`

This is weird, and I'm fixing it. But it uncovered something about how
`if` determines truthiness.

I would expect this code not to output anything, but it does:

foo = SimpleDelegator.new(nil)
puts "hi!" if foo

However, this code does not output anything:

foo = SimpleDelegator.new(nil)
puts "hi!" if !!foo

Are there any docs that describe this behaviour?

Thanks in advance!

Brent

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

Look at foo.class and then at foo.nil?

THEN, consider what happens when asking whether foo _behaves_ like nil or _is_ nil.

-Rob

···

On 2017-Oct-20, at 09:36 , Brent Wheeldon <brent.wheeldon@gmail.com> wrote:

Hi there,

I've come across some code that has edge cases where nil is being passed into a SimpleDelegator-based class.

So, something like `foo = SimpleDelegator.new(nil)`

This is weird, and I'm fixing it. But it uncovered something about how `if` determines truthiness.

I would expect this code not to output anything, but it does:

foo = SimpleDelegator.new(nil)
puts "hi!" if foo

However, this code does not output anything:

foo = SimpleDelegator.new(nil)
puts "hi!" if !!foo

Are there any docs that describe this behaviour?

Thanks in advance!

Brent

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

indicating to me that Truthiness and Falsiness in Ruby are determined by

whether or not something is `FalseClass` or `NilClass`

I think this is exactly it - thank you!

And the reason that `!!foo` works is that `Delegator` delegates `!` to the
underlying object[1] (`nil` in this case) and "does the right thing".

So I think the part I hadn't internalized is that truthiness in ruby seems
to boil down to the expression not being an instance of `NilClass` or
`FalseClass`.

Thanks again!

[1]

···

On 20 October 2017 at 09:47, Eli Sadoff <snood1205@gmail.com> wrote:

Not an expert on this, but I think that the way that this works is that
while `foo = SimpleDelegator.new nil` shows as being `nil` and `foo == nil`
returns true, `foo.nil?` is `false` and `foo.class` returns
`SimpleDelegator` as its class. Furthermore, `foo.is_a? NilClass` returns
`false` whereas `nil.is_a? NilClass` returns `true` indicating to me that
Truthiness and Falsiness in Ruby are determined by whether or not something
is `FalseClass` or `NilClass`. Interestingly, this same behavior applies to
false, you can test it like this

This prints 'wut?'

fl = SimpleDelegator.new false
puts 'wut?' if fl

This prints nothing

fl = SimpleDelegator.new false
puts 'wut?' if !!fl

On Fri, Oct 20, 2017 at 9:36 AM, Brent Wheeldon <brent.wheeldon@gmail.com> > wrote:

Hi there,

I've come across some code that has edge cases where nil is being passed
into a SimpleDelegator-based class.

So, something like `foo = SimpleDelegator.new(nil)`

This is weird, and I'm fixing it. But it uncovered something about how
`if` determines truthiness.

I would expect this code not to output anything, but it does:

foo = SimpleDelegator.new(nil)
puts "hi!" if foo

However, this code does not output anything:

foo = SimpleDelegator.new(nil)
puts "hi!" if !!foo

Are there any docs that describe this behaviour?

Thanks in advance!

Brent

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

It is axiomatic in MOST computer languages that only one of the Boolean values is defined, whilst the other is assumed to be any value other than the defined value. Hence the use of all sorts of short cuts, especially in games programming.

In the case of Ruby, the defined non-true values are false and nil. These are not equivalent as far as I know. Any other numeric value will therefore equate to true.

···

On 20/10/2017 17:04, Brent Wheeldon wrote:

> indicating to me that Truthiness and Falsiness in Ruby are determined by whether or not something is `FalseClass` or `NilClass`

I think this is exactly it - thank you!

And the reason that `!!foo` works is that `Delegator` delegates `!` to the underlying object[1] (`nil` in this case) and "does the right thing".

So I think the part I hadn't internalized is that truthiness in ruby seems to boil down to the expression not being an instance of `NilClass` or `FalseClass`.

Thanks again!

[1] Class: Delegator (Ruby 2.4.2)

On 20 October 2017 at 09:47, Eli Sadoff <snood1205@gmail.com > <mailto:snood1205@gmail.com>> wrote:

    Not an expert on this, but I think that the way that this works is
    that while `foo = SimpleDelegator.new nil` shows as being `nil`
    and `foo == nil` returns true, `foo.nil?` is `false` and
    `foo.class` returns `SimpleDelegator` as its class. Furthermore,
    `foo.is_a? NilClass` returns `false` whereas `nil.is_a? NilClass`
    returns `true` indicating to me that Truthiness and Falsiness in
    Ruby are determined by whether or not something is `FalseClass` or
    `NilClass`. Interestingly, this same behavior applies to false,
    you can test it like this

    This prints 'wut?'

    fl = SimpleDelegator.new false
    puts 'wut?' if fl

    This prints nothing

    fl = SimpleDelegator.new false
    puts 'wut?' if !!fl

    On Fri, Oct 20, 2017 at 9:36 AM, Brent Wheeldon > <brent.wheeldon@gmail.com <mailto:brent.wheeldon@gmail.com>> wrote:

        Hi there,

        I've come across some code that has edge cases where nil is
        being passed into a SimpleDelegator-based class.

        So, something like `foo = SimpleDelegator.new(nil)`

        This is weird, and I'm fixing it. But it uncovered something
        about how `if` determines truthiness.

        I would expect this code not to output anything, but it does:

        foo = SimpleDelegator.new(nil)
        puts "hi!" if foo

        However, this code does not output anything:

        foo = SimpleDelegator.new(nil)
        puts "hi!" if !!foo

        Are there any docs that describe this behaviour?

        Thanks in advance!

        Brent

        Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org
        <mailto:ruby-talk-request@ruby-lang.org>?subject=unsubscribe>
        <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk
        <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;&gt;

    Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org
    <mailto:ruby-talk-request@ruby-lang.org>?subject=unsubscribe>
    <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk
    <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;&gt;

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

--
Patrick Bayford

Any other value (regardless whether numeric or not) will equate to true!

And it is also important to consider how the truthness checks are
implemented. Since Ruby uses tagged pointers there is no method
invocation in play in the first example. The pointer to the instance
of SimpleDelegator is just not one of the "false" values. I did not
find the place in source code quickly but I am pretty sure it is just
a bit operation on the pointer / value (type VALUE in Ruby source).

Kind regards

robert

···

On Fri, Oct 20, 2017 at 10:40 PM, Patrick Bayford <pbayford@talktalk.net> wrote:

It is axiomatic in MOST computer languages that only one of the Boolean
values is defined, whilst the other is assumed to be any value other than
the defined value. Hence the use of all sorts of short cuts, especially in
games programming.

In the case of Ruby, the defined non-true values are false and nil. These
are not equivalent as far as I know. Any other numeric value will therefore
equate to true.

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/