From: declan@... Date: 2018-04-27T16:33:08+00:00 Subject: [ruby-core:86727] [Ruby trunk Bug#14719] FalseClass wrapping a SimpleDelegator evaluates to true in an IF statement Issue #14719 has been reported by theirishpenguin (Declan McGrath). ---------------------------------------- Bug #14719: FalseClass wrapping a SimpleDelegator evaluates to true in an IF statement https://bugs.ruby-lang.org/issues/14719 * Author: theirishpenguin (Declan McGrath) * Status: Open * 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 `
' ~~~ 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 `
' ~~~ 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: