Bug #14719
closedFalseClass wrapped in a SimpleDelegator evaluates to true in an IF statement
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