inopinatus
inopinatus

Reputation: 3779

Nested named argument destructuring in ruby block

I would like to destructure a nested data structure using only block arguments.

The data (simplified for this example) is like this:

response = [
  ["James", { species: "cat", age: "4" }],
  ["Sandy", { species: "dog", age: "7" }],
  ["Horse", { species: "man", age: "34" }]
]

I can't find a syntax valid for destructuring this using only block arguments. I imagined it might be this, combining the nested-array destructuring style with named keyword arguments:

response.map do |name, (species:, age:)|
  "#{name}: #{species}, #{age}"
end

but that gives a syntax error.

Obviously there are plenty of other ways to extract the necessary data e.g. using non-nested keyword arguments:

response.map do |name, data|
  proc { |species:, age:|
    "#{name}: #{species}, #{age}"        
  }.(data)
end

or

response.map do |name, data|
  species, age = data.values_at(:species, :age)
  "#{name}: #{species}, #{age}"        
end

or the very obvious

response.map do |name, data|
  "#{name}: #{data[:species]}, #{data[:age]}"
end

but I'd love to have it in the block arguments, because it appeals to my sense of elegant code. Any ideas?

Upvotes: 5

Views: 1100

Answers (1)

Amadan
Amadan

Reputation: 198324

|name, species:, age:| works (because of the way keyword arguments are handled). It obviously won't work in the general case, but due to the way keyword arguments work, an array whose last element is a hash cleanly corresponds to a parameter list.

Upvotes: 5

Related Questions