From: ntalbott@... Date: 2002-01-31T23:08:29+09:00 Subject: RE: Proc hash bug? Chr. Rippel [mailto:chr_news@gmx.net] wrote: > Well looking at the source in eval.c 6567-82 > > static VALUE > proc_to_s(self, other) > VALUE self, other; > { > struct BLOCK *data; > char *cname = rb_class2name(CLASS_OF(self)); > VALUE str; > > Data_Get_Struct(self, struct BLOCK, data); > str = rb_str_new(0, strlen(cname)+6+16+1); /* 6:tags 16:addr 1:nul */ > sprintf(RSTRING(str)->ptr, "#<%s:0x%lx>", cname, data->tag); > RSTRING(str)->len = strlen(RSTRING(str)->ptr); > if (OBJ_TAINTED(self)) OBJ_TAINT(str); > > return str; > } So the number it's printing is data->tag? What is that used for other than to_s? Is it subject to change? I'm sorry about asking questions that are so basic, but I'm no C guru (nor even really a C guy), and I have no familiarity with the Ruby C sources. > it should not be hard to write this as an extension - > actually its probably not such bad idea to write up an RCR > (there was a similar situation about #== I believe). So what RCR are you proposing? Access to data->tag? Or something else? > Using data->tag as a hash value seems save to me - anyway for now > you also could(should) write > > class Proc > alias :eql? :== > def hash > inspect.sub(/^(#)$/){''}.to_i(16) > end > end Here's what I came up with: require 'test/unit' class TC_ProcWrapper < Test::Unit::TestCase def munge_proc(&a_proc) return a_proc end def setup @original = proc {} @munged = munge_proc(&@original) @wrapped_original = ProcWrapper.new(@original) @wrapped_munged = ProcWrapper.new(@munged) end def test_wrapping assert_same(@original, @wrapped_original.to_proc, "The wrapper should return what was wrapped") end def test_hashing assert_not_equal(@original.hash, @munged.hash, "The original and munged procs should not have the same hash") assert_equal(@wrapped_original.hash, @wrapped_munged.hash, "The original and munged should have the same hash when wrapped") assert_equal(@wrapped_original, @wrapped_munged, "The wrappers should be equivalent") a_hash = {@wrapped_original => @original} assert_not_nil(a_hash[@wrapped_original], "Should be able to access the wrapper in the hash") end end class ProcWrapper def initialize(a_proc) @a_proc = a_proc @hash = a_proc.inspect.sub(/^(#<#{a_proc.type}:)/){''}.sub(/(>)$/){''}.hex end def hash return @hash end def ==(other) case(other) when ProcWrapper return @a_proc == other.to_proc else return super end end alias :eql? :== def to_proc return @a_proc end end Loaded suite TI_ProcWrapper Started... ... Finished in 0.0 seconds. 2 runs, 5 assertions, 0 failures, 0 errors I think I'll use this for now... but I'd still appreciate some more discussion (matz?) on why this is necessary. Thanks, Nathaniel <:((>< + - - | RoleModel Software, Inc. | EQUIP VI