views:

271

answers:

3

I need a ruby hash H with keys :a, :b, :c so that H[:b] = H[:a] + 1; H[:c] = H[:b] + 2 etc.

How can I define such a hash in a one line declaration, like H = {:a=>1, :b => H[:a] + 1, :c => H[:b] +2, ... } ?

I need something similar to DataMapper properties declaration:

property :path, FilePath

property :md5sum, String, :default => lambda { |r, p| Digest::MD5.hexdigest(r.path.read)}

where :md5sum default value is referencing the :path property

A: 

This is the best I can do:

arr = [[:a,1], [:b,1], [:c,2]]; H = {:temp => 0}
arr.inject(:temp) { |last, kv| H[kv[0]] = H[last] + kv[1]; kv[0] }
H.delete :temp

Pretty ugly, and it isn't so obvious what it does. I suggest you just do it the straightforward way, unless it's really that much of a problem.

ehsanul
A: 

It's not clear what you are trying to accomplish. Note that hashes can have a default proc. Ex:

require 'digest/md5'
h = Hash.new do |hash, key|
  hash[:md5sum] = Digest::MD5.hexdigest(hash[:path]) if key == :md5sum
end

h[:path] = "/starway/to/heaven"
h[:md5sum]  # ==> "0e4faf226dac83569bde4fcf5bcd7ad6"
h[:md5sum] = "xyz"
h[:md5sum]  # ==> "xyz"
Marc-André Lafortune
a way of doing it is:H = {}; H[:a] = 1; H[:b] = H[:a] + 1; H[:c] = H[:b] + 2; etc.I was just wondering if the declaration and initialization of the hash H (whose elements refer to some other elements of the same hash) could be done in one line - all in one place at the same time.
Alpinweis
Maybe if you posted a real example it would be clearer. :a, :b, +1, etc.. are probably not what you are doing here!
Marc-André Lafortune
A: 

It sounds like you may want lazy declarations: http://moonbase.rydia.net/software/lazy.rb/

Trevoke