We're updating the issue view to help you get more done. 

Enable destructuring of sequency maps

Description

At present, Clojure's destructuring implementation will create a hash-map from any encountered value satisfying clojure.core/seq? This has the I argue undesirable side effect of making it impossible to employ destructuring on a custom Associative type which is also a Seq. This came up when trying to destructure instances of a tagged value class which for the purpose of pattern matching behave as [k v] seqs, but since the v is known to be a map, are also associative on the map part so as to avoid the syntactic overhead of updates preserving the tag.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ;; A sketch of such a type (deftype ATaggedVal [t v] clojure.lang.Indexed (nth [self i] (nth self i nil)) (nth [self i o] (case i (0) t (1) v o)) clojure.lang.Sequential clojure.lang.ISeq (next [this] (seq this)) (first [this] t) (more [this] (.more (seq this))) (count [this] 2) (equiv [this obj] (= (seq this) obj)) (seq [self] (cons t (cons v nil))) clojure.lang.Associative (entryAt [self key] (.entryAt v key)) (assoc [_ sk sv] (ATaggedVal. t (.assoc v sk sv))) clojure.lang.ILookup (valAt [self k] (.valAt v k)) (valAt [self k o] (.valAt v k o)) clojure.lang.IPersistentMap (assocEx [_ sk sv] (ATaggedVal. t (.assocEx v sk sv))) (without [_ sk] (ATaggedVal. t (.without v sk))))

So using such a thing,

1 2 3 (let [{:keys [x]} (ATaggedVal. :foo {:x 3 :y 4})] x) ;; expect 3 => nil

Since for any type T such that clojure.core/get will behave, T should satisfy clojure.core/map? it should be correct simply to change the behavior of destructure to only build a hash-map if map? isn't already satisfied.

The attached patch makes this change.

Environment

None

Status

Assignee

Unassigned

Reporter

Reid D McKenzie

Labels

Approval

Triaged

Patch

Code

Priority

Minor