Today Icelab Learned

Hash.new with a block works well as a keyed cache

We’re all familiar with the @foo ||= expensive_computation technique to memoize (i.e. cache) the output of slow computations or to avoid unnecessary object creation.

If you want to do the same but with results that will vary by a single parameter, you can use Ruby’s hash with its block-based initializer to handle the caching for you:

def my_cache
  @my_cache ||= Hash.new do |hash, key|
    hash[key] = some_slow_computation(key)
  end
end

# Computed once
my_cache[:foo]

# Then cached
my_cache[:foo]

You can see this work in practice inside dry-component’s Injector, where it caches objects to allow arbitrarily long chaining of injector strategies without creating duplicate injector objects.