On Sat, 19 Jul 2003 23:22:20 +0900
Gavin Sinclair <gsinclair / soyabean.com.au> wrote:

> Hi -talk,
> 
> Ruby has wonderful support for chewing and spitting arrays.  For
> instance, it's easy to produce an array from any Enumerable using
> #map.  With hashes, however, it's a bit more cumbersome.
> 
> For example, the following method is typical of my code:
> 
>     # return { filename -> size }
>   def get_local_gz_files
>     files = {}
>     Dir["*.gz"].each do |filename|
>       files[filename] = File.stat(filename).size
>     end
>     files
>   end

One option, in this case, is to hijack the Hash#new block form:

files = Hash.new { |hash, key| hash[key] = File.stat(key).size }

files is now a "magic" hash that will stat any file that that's used as a key.
If you're not just doing random access, you could fill it like so:

Dir["*.gz"].each { |f| files[f] }

The block will be called to return a value instead of nil when a key is missing:
We assign to the hash to save that value as well. You can do all *sorts* of
weird stuff using this feature:

>> e = Hash.new { |h, k| eval(k) }
=> {}
>> e["Time.now"] 
=> Tue Jul 22 13:32:56 MDT 2003
<wait a couple seconds>
>> e["Time.now"]
=> Tue Jul 22 13:33:03 MDT 2003
>> e = Hash.new { |h, k| h[k] = eval(k) }
=> {}
>> e["Time.now"]
=> Tue Jul 22 13:35:09 MDT 2003
<wait a couple seconds>
>> e["Time.now"]
=> Tue Jul 22 13:35:09 MDT 2003

Jason Creighton