Issue #14719 has been updated by marcandre (Marc-Andre Lafortune).

Status changed from Open to Rejected

I'm afraid you can not achieve what you want to achieve in Ruby. The only two objects that are falsy in Ruby are `nil` and `false`. No other object can "look" like `false`. This is by design and can not be changed.

----------------------------------------
Bug #14719: FalseClass wrapping a SimpleDelegator evaluates to true in an IF statement
https://bugs.ruby-lang.org/issues/14719#change-71692

* Author: theirishpenguin (Declan McGrath)
* Status: Rejected
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
Hi, thanks for Ruby :-)

I have run into a problem. When I wrap the boolean false in a SimpleDelegator it breaks the semantics of the boolean when evaluated in expressions such as IF statements - returning true when I would have expected false.

Here is a test case...

~~~ ruby
class BoldBool < SimpleDelegator                                                                                        
end                                                                                                                     
                                                                                                                        
false_bool = BoldBool.new(false)                                                                                        
                                                                                                                        
if false_bool                                                                                                           
    puts "I'm evaluated as true but I should be false."                                                                 
end 
~~~

When I run it I get:
#=>I'm evaluated as true but I should be false.

Expected result:
No output.

I understand that there may be good reasons for why this is happening (eg. the class of the object false_bool may be a BoldBool and this is not a FalseClass) however it breaks the fundamental semantics of a boolean - in which case I think we should consider raising an ArgumentError in the Ruby language if a Boolean is passed to the constructor of a SimpleDelegator.

I tried to workaround the problem by overriding equals?(). I am guessing that this would be the correct approach - and that this is what is used by the IF expression to determine whether it is dealing with a truthy object or a falsey...

~~~ ruby
class BoldBool < SimpleDelegator                                                                                        
    def equal?(obj)                                                                                                     
        if __getobj__.is_a? FalseClass and obj == false                                                                 
            return true                                                                                                 
        else                                                                                                            
            __getobj__.equal?(obj)                                                                                      
        end                                                                                                             
    end                                                                                                                 
end                                                                                                                     
                                                                                                                        
false_bool = BoldBool.new(false)                                                                                        
                                                                                                                        
if false_bool                                                                                                           
    puts "I'm evaluated as true but I should be false."                                                                 
end
~~~

However this gives me the error...

~~~ ruby
/home/me/.rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/delegate.rb:313:in `__getobj__': not delegated (ArgumentError)
        from simple_delegator_on_boolean_with_equals_override.rb:5:in `equal?'
        from /home/me/.rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/delegate.rb:333:in `__setobj__'
        from /home/me/.rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/delegate.rb:72:in `initialize'
        from simple_delegator_on_boolean_with_equals_override.rb:13:in `new'
        from simple_delegator_on_boolean_with_equals_override.rb:13:in `<main>'
~~~

If I try an even simpler override approach as an experiment this errors too...

~~~ ruby
class BoldBool < SimpleDelegator                                                                                        
    def equal?(obj)                                                                                                     
        true                                                                                                            
    end                                                                                                                 
end                                                                                                                     
                                                                                                                        
false_bool = BoldBool.new(false)                                                                                        
                                                                                                                        
if false_bool                                                                                                           
    puts "I'm evaluated as true but I should be false."                                                                 
end      
~~~

... with the error...

~~~ ruby
/home/me/.rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/delegate.rb:333:in `__setobj__': cannot delegate to self (ArgumentError)
        from /home/me/.rvm/rubies/ruby-2.4.1/lib/ruby/2.4.0/delegate.rb:72:in `initialize'
        from simple_delegator_on_boolean_with_simple_equals_override.rb:9:in `new'
        from simple_delegator_on_boolean_with_simple_equals_override.rb:9:in `<main>'
~~~

Is this SimpleDelegator behaviour a bug? (downloadable files attached containing the above snippets).

---Files--------------------------------
simple_delegator_on_boolean.rb (167 Bytes)
simple_delegator_on_boolean_with_equals_override.rb (335 Bytes)
simple_delegator_on_boolean_with_simple_equals_override.rb (208 Bytes)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>