* [ruby-dev:49187] [Ruby trunk - Bug #11381] [Open] String のサブクラスをハッシュのキーに指定した時に hash メソッドが呼ばれない
[not found] <redmine.issue-11381.20150721142357@ruby-lang.org>
@ 2015-07-21 14:23 ` tommy
2019-07-05 3:23 ` [ruby-dev:50809] [Ruby master Bug#11381] " merch-redmine
1 sibling, 0 replies; 2+ messages in thread
From: tommy @ 2015-07-21 14:23 UTC (permalink / raw)
To: ruby-dev
Issue #11381 has been reported by Masahiro Tomita.
----------------------------------------
Bug #11381: String のサブクラスをハッシュのキーに指定した時に hash メソッドが呼ばれない
https://bugs.ruby-lang.org/issues/11381
* Author: Masahiro Tomita
* Status: Open
* Priority: Normal
* Assignee:
* ruby -v: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
----------------------------------------
String のサブクラスとして大文字小文字を同一視するようなクラスを作ろうとしましたが、
そのオブジェクトをハッシュのキーに指定しても期待通りに動作しませんでした。
どうやら hash メソッドが呼ばれていないようです。
```ruby
class CIString < String
def eql?(other)
self.casecmp(other) == 0
end
def hash
self.to_s.downcase.hash
end
end
h = {}
k1 = CIString.new("hoge")
k2 = CIString.new("HOGE")
p k1.eql? k2 #=> true
p k1.hash == k2.hash #=> true
h[k1] = 1
h[k2] = 2
p h #=> {"hoge"=>1, "HOGE"=>2}
```
ちなみに eql? の方はちゃんと呼ばれるようで、次のようにすると同じ値であっても別のキーとみなされます。
```ruby
class CIString < String
def eql?(other)
false
end
end
h = {}
k1 = CIString.new("hoge")
k2 = CIString.new("hoge")
h[k1] = 1
h[k2] = 2
p h #=> {"hoge"=>1, "hoge"=>2}
```
次のパッチで期待通りにサブクラスの hash メソッドが呼びだされました。
```diff
diff --git a/hash.c b/hash.c
index 7b8733f..26e5a3d 100644
--- a/hash.c
+++ b/hash.c
@@ -145,7 +145,7 @@ rb_any_hash(VALUE a)
}
hnum = rb_objid_hash((st_index_t)a);
}
- else if (BUILTIN_TYPE(a) == T_STRING) {
+ else if (BUILTIN_TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString) {
hnum = rb_str_hash(a);
}
else if (BUILTIN_TYPE(a) == T_SYMBOL) {
```
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 2+ messages in thread
* [ruby-dev:50809] [Ruby master Bug#11381] String のサブクラスをハッシュのキーに指定した時に hash メソッドが呼ばれない
[not found] <redmine.issue-11381.20150721142357@ruby-lang.org>
2015-07-21 14:23 ` [ruby-dev:49187] [Ruby trunk - Bug #11381] [Open] String のサブクラスをハッシュのキーに指定した時に hash メソッドが呼ばれない tommy
@ 2019-07-05 3:23 ` merch-redmine
1 sibling, 0 replies; 2+ messages in thread
From: merch-redmine @ 2019-07-05 3:23 UTC (permalink / raw)
To: ruby-dev
Issue #11381 has been updated by jeremyevans0 (Jeremy Evans).
Status changed from Open to Feedback
This behavior hasn't changed since the initial report. However, it seems odd to just treat string subclasses (or strings with singleton classes) differently. Currently the behavior is to use C functions for (at least) String, Symbol, Integer, and Float, probably for performance. Your example could apply to someone that wanted to modify the behavior of all strings instead of just a specific string subclass. So I wouldn't consider this an implementation detail, not a bug. There are a lot of cases where Ruby calls C functions instead of Ruby methods internally for performance.
I think you can get something that works fairly well using delegate:
```ruby
require 'delegate'
class CIString < DelegateClass(String)
def hash
downcase.hash
end
alias to_str __getobj__
alias eql? casecmp?
end
h = {}
k1 = CIString.new("hoge")
k2 = CIString.new("HOGE")
p k1.eql? k2 #=> true
p k1.hash == k2.hash #=> true
h[k1] = 1
h[k2] = 2
p h
# {"hoge"=>2}
```
Do you think that would work for you?
----------------------------------------
Bug #11381: String のサブクラスをハッシュのキーに指定した時に hash メソッドが呼ばれない
https://bugs.ruby-lang.org/issues/11381#change-79120
* Author: tommy (Masahiro Tomita)
* Status: Feedback
* Priority: Normal
* Assignee:
* Target version:
* ruby -v: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
----------------------------------------
String のサブクラスとして大文字小文字を同一視するようなクラスを作ろうとしましたが、
そのオブジェクトをハッシュのキーに指定しても期待通りに動作しませんでした。
どうやら hash メソッドが呼ばれていないようです。
```ruby
class CIString < String
def eql?(other)
self.casecmp(other) == 0
end
def hash
self.to_s.downcase.hash
end
end
h = {}
k1 = CIString.new("hoge")
k2 = CIString.new("HOGE")
p k1.eql? k2 #=> true
p k1.hash == k2.hash #=> true
h[k1] = 1
h[k2] = 2
p h #=> {"hoge"=>1, "HOGE"=>2}
```
ちなみに eql? の方はちゃんと呼ばれるようで、次のようにすると同じ値であっても別のキーとみなされます。
```ruby
class CIString < String
def eql?(other)
false
end
end
h = {}
k1 = CIString.new("hoge")
k2 = CIString.new("hoge")
h[k1] = 1
h[k2] = 2
p h #=> {"hoge"=>1, "hoge"=>2}
```
次のパッチで期待通りにサブクラスの hash メソッドが呼びだされました。
```diff
diff --git a/hash.c b/hash.c
index 7b8733f..26e5a3d 100644
--- a/hash.c
+++ b/hash.c
@@ -145,7 +145,7 @@ rb_any_hash(VALUE a)
}
hnum = rb_objid_hash((st_index_t)a);
}
- else if (BUILTIN_TYPE(a) == T_STRING) {
+ else if (BUILTIN_TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString) {
hnum = rb_str_hash(a);
}
else if (BUILTIN_TYPE(a) == T_SYMBOL) {
```
--
https://bugs.ruby-lang.org/
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-07-05 3:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <redmine.issue-11381.20150721142357@ruby-lang.org>
2015-07-21 14:23 ` [ruby-dev:49187] [Ruby trunk - Bug #11381] [Open] String のサブクラスをハッシュのキーに指定した時に hash メソッドが呼ばれない tommy
2019-07-05 3:23 ` [ruby-dev:50809] [Ruby master Bug#11381] " merch-redmine
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).