From: Gavin Sinclair Date: 2002-11-04T08:32:02+09:00 Subject: Re: Extending Hash From: "Carl Youngblood" > I'm trying to create a modified version of a Hash that, if it doesn't contain anything for a given key, will return whatever element it has that most closely matches the key. Here's what I've done so far: > > ----------------------------------- > class FragHash < Hash > def [](key) > index = key.dup > while !self.has_key?(index) and index.chop! != nil > end > return self.default if index.empty? > return fetch(index) > end > end > ----------------------------------- A Ruby-idiomatic way to do the while loop might be: 1 until self.has_key?(index) or index.chop! == nil Use it if you think it's more readable. > so if I do the following: > > ----------------------------------- > h = FragHash.new > h['t'] = 23 > puts h['test'] > ----------------------------------- > the output is 23. In other words, it didn't find the index "test" but it kept shortening the index until it found something that matches. The only problem I have now is that I want to make it so that when I call each() it also enumerates through the default value. However, I don't know how to extend the each function (I'm still a little hazy on how to overload functions that use blocks). It would be nice if I could look at the source for the Hash class itself. Does anyone know where I can find it? Does anyone have any suggestions for how I might modify the each function? > > Thanks, > Carl Youngblood I'm not actually sure or your problem here Carl. What do you mean by the "default" value? In your example above, won't "each" yield ["t", 23]? Anyway, overriding each is not too hard. Here's how you could implement Hash#each from scratch if you wanted to. You can hopefully use this to implement the functionality you want. (Warning, not tested.) class Hash def each(&block) self.keys.each do |key| value = self.[key] block.call(key, value) end end end Hope this helps, Gavin