Project

General

Profile

Actions

Bug #14719

closed

FalseClass wrapped in a SimpleDelegator evaluates to true in an IF statement

Added by theirishpenguin (Declan McGrath) almost 6 years ago. Updated almost 6 years ago.

Status:
Rejected
Assignee:
-
Target version:
-
ruby -v:
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
[ruby-core:86727]

Description

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...

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...

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...

/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...

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...

/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.rb theirishpenguin (Declan McGrath), 04/27/2018 04:16 PM
simple_delegator_on_boolean_with_equals_override.rb (335 Bytes) simple_delegator_on_boolean_with_equals_override.rb theirishpenguin (Declan McGrath), 04/27/2018 04:16 PM
simple_delegator_on_boolean_with_simple_equals_override.rb (208 Bytes) simple_delegator_on_boolean_with_simple_equals_override.rb theirishpenguin (Declan McGrath), 04/27/2018 04:17 PM

Updated by marcandre (Marc-Andre Lafortune) almost 6 years ago

  • 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.

Updated by theirishpenguin (Declan McGrath) almost 6 years ago

Thanks Marc-Andre. Appreciate the quick response.

Actions #3

Updated by theirishpenguin (Declan McGrath) almost 6 years ago

  • Subject changed from FalseClass wrapping a SimpleDelegator evaluates to true in an IF statement to FalseClass wrapped in a SimpleDelegator evaluates to true in an IF statement
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0