Destructuring defaults that refer to other destructued values no longer?

In older versions of Clojurescript we were able to make defaults that refer to other defaults. Upon upgrading my library I find this is broken. Is there a syntactic nuance I should know to fix this, or should I do a little more computation upon it?

(defn foo
  [{:keys [id vpath]
    :or {id "generic-id"
	 vpath [(keyword id)] ;; TODO newest clojure seems not to allow this
	 } :as m}]
  ;; function body
  )

According to at least Alex Miller, relying in destructuring on previously destructured values has always been an undefined behavior. One such message, quickly found on Slack (although there have been many): Slack

And it makes even more sense when you think how a map can have enough keys to stop being an array map and become a hash map, where the order is undefined.

2 Likes

I always thought that this was an awesome feature. I even recall making a bug report to Cursive, since it didn’t seem to support it. I had no idea it was undefined behaviour :grinning_face_with_smiling_eyes:

Couldn’t the :or part in theory determine the order of look-up?

On the other hand, destructuring is already expressive enough to scare away newcomers, so maybe it’s a good place to stop :slight_smile:

1 Like

I agree that this was unreliable behavior; once upon a time I was surprised it even worked. I’m only suprised that a clojure upgrade broke my syntax, since that is so rare (even though that kind of uncertainty is the definition of “undefined behavior”). I fixed my code by doing the dependent destructuring in a “let”, which is sequential in its behavior. . So no big deal. I was mostly curious on the genesis of the breakage I experienced.