0 Replies - 2098 Views - Last Post: 28 September 2018 - 12:15 AM

#1 Lemur   User is offline

  • Pragmatism over Dogma
  • member icon


Reputation: 1453
  • View blog
  • Posts: 3,633
  • Joined: 28-November 09

Block destructuring

Posted 28 September 2018 - 12:15 AM

def destructure(object, &fn)
  values = fn.parameters.map(&:last).map { |m| object.public_send(m) }
  fn.call(*values)
end

Point = Struct.new(:x, :y)

destructure(Point.new(0, 0)) { |x, y| Point.new(x + 5, y + 1) }
# => #<struct Point x=5, y=1>



Blocks (or functions) in Ruby have a method called parameters, which returns the types and names of the arguments as such:

-> x, y { }.parameters
=> [[:req, :x], [:req, :y]]



In the first part of destructure, we extract the names of that block function, giving us back an array of :x and :y.

Using these as method names, we map over that array and extract the values of that object at that method. In this case, x and y, the Struct's properties.

After we have these values, we can then call the function with those extracted values.

This effectively gives the ability to arbitrarily extract values of an object just based on function argument names:

destructure(Point.new(0, 0)) { |to_s, to_h, to_a| [to_s, to_h, to_a] }
# => ["#<struct Point x=0, y=0>", {:x=>0, :y=>0}, [0, 0]]



Now with great power comes great irresponsibility. Enjoy!

Is This A Good Question/Topic? 0
  • +

Page 1 of 1