From: Josh Cheek Date: 2011-04-28T14:03:32+09:00 Subject: Re: Hash pointing to reference of itself! --20cf3071cfae5a398d04a1f37813 Content-Type: text/plain; charset=ISO-8859-1 On Wed, Apr 27, 2011 at 9:06 PM, Peter Ehrlich wrote: > Hey! > > Supposed I want have a hash, with one key always holding the value of > another key. Is this possible without referencing outside the hash > closure? Forgive my lack of understanding of ruby internals. > > Cheers! > > -- > Posted via http://www.ruby-forum.com/. > > You can't do that, that would require variables being able to point to other variables. You could, however, fake it by creating your own hash which allows this functionality, as shown below. It just has an internal hash that allows keys to refer to other keys, then when you request one, it follows the chain of referrals until it arrives at an end point, and gives you back that key. While this is a bit interesting, it is more likely that whatever you are trying to do is not the Ruby way of solving your problem. Are you coming from a language like C++ where you have direct access to pointers and references? You might be trying to write Ruby like it is that other language. Perhaps if you tell us more about your use case, we can offer a solution that is better than "this technically does what you are requesting". class RHash def initialize @data = Hash.new @references = Hash.new end def [](key) return nil unless in_reference_chain? key @data[actual key] end def []=(key,value) @data[actual key] = value end def refer(references) references.each do |from, to| reference_chain from, to @data.delete from if orphaned? from end end private def orphaned?(from) @references[from] != from end def in_reference_chain?(key) @references.has_key? key end def reference_chain(from, to=from) @references[from] = to end def actual(key) reference_chain key unless in_reference_chain? key referenced = @references[key] return referenced if referenced == key return actual referenced end end h = RHash.new h[:foo] # => nil h[:foo] = 5 h[:foo] # => 5 h[:bar] # => nil h.refer :bar => :foo h[:bar] # => 5 h[:foo] = 6 h[:bar] # => 6 h # => #6}, @references={:foo=>:foo, :bar=>:foo}> h.refer :foo => :baz h # => #:baz, :bar=>:foo}> h[:baz] = 12 h[:foo] # => 12 h[:bar] # => 12 h[:baz] # => 12 h[:foo] = 40 h[:foo] # => 40 h[:bar] # => 40 h[:baz] # => 40 h.refer :foo => :foo h # => #40}, @references={:foo=>:foo, :bar=>:foo, :baz=>:baz}> h[:foo] # => nil h[:bar] # => nil h[:baz] # => 40 h["garlic"] = "vampire" h.refer :foo => 'garlic', :bar => :baz h[:foo] # => "vampire" h['garlic'] # => "vampire" h[:bar] # => 40 h[:baz] # => 40 note: if you decide you actually want to use this code, let me know, and I'll give you the "test suite" I used while writing it. --20cf3071cfae5a398d04a1f37813--