Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

a set of strings and reopening String

Tags:

ruby

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'
like image 475
akonsu Avatar asked Dec 21 '12 17:12

akonsu


1 Answers

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
like image 74
Luke Avatar answered Oct 20 '22 03:10

Luke