Destructuring in Clojure and Ruby

As a long time Rubyist who picked up Clojure earlier this year, I have noticed the following pattern repeats itself:

  1. Encounter some new concept in Clojure
  2. Become confused by said concept and spin my wheels for a bit
  3. Realize I was using this concept in Ruby without knowing its name and full potential
  4. Simultaneously level up Ruby and Clojure skills

Destructuring is the perfect example of one such concept. Per the offical Clojure documentation:

Clojure supports abstract structural binding, often called destructuring, in let binding lists, fn parameter lists, and any macro that expands into a let or fn.

It was not immediately obvious to me based on this definition, but this is actually quite common in Ruby. Consider the following:

1
2
3
4
5
some_hash = {a:1,b:2,c:1}

some_hash.each do |(k,v)|
  # do stuff
end

Using (k, v) effectively tells Ruby:

  1. This element has two parts
  2. Assign the first part of that element to “k”
  3. Assign the second part of that element to “v”

Destructuring within list comprehenstions in Clojure looks remarkably similar:

1
2
3
(defn use-a-hashmap [some-hashmap]
  (for [[k v] some-hashmap]
   ; do amazing functional things

We can also destructure method arguments in Ruby. Consider a method that takes a three element array as an argument. Instead of this:

1
2
3
4
def do_thing_with_point(point)
  x, y, z = point
  # do stuff
end

We can use destructuring to skip a step:

1
2
3
def do_thing_with_point((x,y,z))
  # do stuff
end

As with many things in Ruby, the better question than “Can it be done this way?” is “Is it wise?”. Think this is a win because the second example gives (slightly!) more immediate insight into the argument this method accepts.