Props to Jeremy Voorhis for this cool and simple Hash maneuver.

class Hash
  def rewrite mapping
    inject({}) do |rewritten_hash, (original_key, value)|
      rewritten_hash[mapping.fetch(original_key, original_key)] = value
      rewritten_hash
    end
  end
end

Example usage:

h = { :human => 'squishy', :robot => 'tinny' }
h.rewrite(:human => :mammal)
# => { :mammal => 'squishy', :robot => 'tinny' }

Interestingly, this is the first time I’ve seen argument decomposition used in a truly clear and helpful way.

3 Comments

  1. Bill Burcham

    That’s a beautiful method. Which part is the “argument decomposition” part? I Googled for “ruby argument decomposition” about all I get is this very post!

  2. duncanbeevers

    A block passed to inject takes two arguments. The first is the accumulator, and the second is the element of the enumerable being injected (or folded.)

    The decomposition in this case occurs in the second argument of the inject block, which instead of assigning the enumerable element to a single block-local variable, instead decomposes the Hash tuple (key, value) to two discrete locals. Neat!

  3. Bill Burcham

    Oh yeah. For folks who want to find more of these in the wild, here’s a TextMate regexp that will find all injects that use argument decomposition:

    inject.*[|][^|(\n]*[(][^)|\n]+[)][^|\n]*[|]

    That makes sense when injecting on anything whose each method yields an array and Hash is a real common one (yielding [key,value]).

Leave a Comment

Enclose code in <code lang="ruby"></code> if you care.
Preview your comment using the button below.