Nuisances with map destructuring

Just venting about a couple of nuisances that came up while refactoring a function to take all args in a map.

  • Can’t provide :keys an array thanks to spec errors. I used to sometimes destructure with (let [ks [:someof :the :keys] {:keys ks} :argmap]) but this is now illegal; the :keys value needs to receive a literal inlined vector.

  • I had a function taking two args, the second an option map. I made it into one arg by moving the first args into the map but lost the ability to refer to the first arg as I derive the default values of map entries, since map default values cannot refer to other values of the same map.

    I’m just venting and don’t need solution ideas, unless theres an easy syntax fix that I missed short of using macros. I know that there are sensible technical reasons for both of these behaviors.

I didn’t think that had ever been legal?

I tried this on every version of Clojure from 1.1 to 1.9 and it fails on all of them:

for v in 1 2 3 4 5 6 7 8 9
  echo Clojure 1.$v
  clojure -M:1.$v -e '(let [ks [:a :b :c] {:keys ks} {}] [a b c])'

1.1 through 1.8 fail with:

Don't know how to create ISeq from: clojure.lang.Symbol

1.9 fails with:

Call to clojure.core/let did not conform to spec:
In: [0 2 :keys] val: ks fails spec: :clojure.core.specs.alpha/keys at: [:args :bindings :binding :map :keys] predicate: vector?

(or was this in ClojureScript?)

doh! I’m sure I did it at some point, though. For things like testing and reasoning over the desired keys, it was handy.