[#70843] Re: [ruby-cvs:58952] hsbt:r51801 (trunk): * lib/rubygems: Update to RubyGems HEAD(fe61e4c112). — Eric Wong <normalperson@...>
hsbt@ruby-lang.org wrote:
3 messages
2015/09/17
[ruby-core:70659] [Ruby trunk - Feature #11505] [Open] Module#=== should call #kind_of? on the object rather than rb_obj_is_kind_of which only searches the ancestor heirarchy
From:
lamont@...
Date:
2015-09-03 18:43:54 UTC
List:
ruby-core #70659
Issue #11505 has been reported by Lamont Granquist.
----------------------------------------
Feature #11505: Module#=== should call #kind_of? on the object rather than rb_obj_is_kind_of which only searches the ancestor heirarchy
https://bugs.ruby-lang.org/issues/11505
* Author: Lamont Granquist
* Status: Open
* Priority: Normal
* Assignee:
----------------------------------------
In trying to implement a Decorator pattern which wraps Hashes and/or Arrays, I would like case equality to work such that the decorator would be handled by case statements on Array or Hash:
```
case
when 'Array'
# handle Arrays
when 'Hash'
# handle Hashes
end
```
My decorators delegate #is_a? and #kind_of? to the decorated object so that #is_a?(Hash) or #kind_of?(Hash) return true even though the decorator does not inherit from Array or Hash.
When trying to use the decorator in case statements, however, the case-equality is handled by Array#=== or Hash#===. This is a method inherited from Module#=== which calls rb_obj_is_kind_of:
https://github.com/ruby/ruby/blob/f830ace8a831a954db7a6aae280a530651a5b58a/object.c#L1519-L1533
The implementation of rb_obj_is_kind_of does not call arg#kind_of?(mod) as its name might suggest, but instead searches the ancestor hierarchy:
https://github.com/ruby/ruby/blob/f830ace8a831a954db7a6aae280a530651a5b58a/object.c#L616-L651
The result of this is that even though my decorator implements the Hash contract, even though it responds to #is_a?(Hash) and #kind_of?(Hash) with true, it cannot be considered a Hash in a case statement short of monkeypatching the core Hash#=== operator.
A proposed fix would be to simply replace the rb_obj_is_kind_of call with:
rb_funcall(arg, rb_intern("kind_of?"), mod)
A more aggressive fix might be to modify the implementation of rb_obj_is_kind_of but that is called at multiple other places in the source code.
This is likely only going to be acceptable for ruby-3.0 and be considered a potentially breaking change I would imagine.
--
https://bugs.ruby-lang.org/