In an attempt to answer this question: How can I make the set difference insensitive to case?, I was experimenting with sets and strings, trying to have a case-insensitive set of strings. But for some reason when I reopen String class, none of my custom methods are invoked when I add a string to a set. In the code below I see no output, but I expected at least one of the operators that I overloaded to be invoked. Why is this?
EDIT: If I create a custom class, say, String2, where I define a hash method, etc, these methods do get called when I add my object to a set. Why not String?
require 'set'
class String
alias :compare_orig :<=>
def <=> v
p '<=>'
downcase.compare_orig v.downcase
end
alias :eql_orig :eql?
def eql? v
p 'eql?'
eql_orig v
end
alias :hash_orig :hash
def hash
p 'hash'
downcase.hash_orig
end
end
Set.new << 'a'
Looking at the source code for Set
, it uses a simple hash for storage:
def add(o)
@hash[o] = true
self
end
So it looks like what you need to do instead of opening String
is open Set
. I haven't tested this, but it should give you the right idea:
class MySet < Set
def add(o)
if o.is_a?(String)
@hash[o.downcase] = true
else
@hash[o] = true
end
self
end
end
Edit
As noted in the comments, this can be implemented in a much simpler way:
class MySet < Set
def add(o)
super(o.is_a?(String) ? o.downcase : o)
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With