This is related to a number of other asks/jira tickets but I haven't found one for this specifically.
Because :or
is destructured into not-found
values of the get
calls for the destructured keys/symbols/etc, if you bind an object with :as
and include defaults in :or
, the object won't have the defaults:
(defn example [{:keys [a b]
:or {a 1 b 2}
:as opts}]
(println a b opts))
(example {:a 5})
;=> 5 2 {:a 5}
This has led to subtle bugs in our codebase where we expected the defaults to exist and then they didn't, or we used {:pre [some-pred]}
to check an invariant which was violated when we modified the function to use :as
in addition to the specific values.
To merge them, you'd want to build the map and then opts (conj defaults-map opts)
, but that requires iterating over the keys/syms/strs a second time, selecting only the names in the :or
map and requires creating another map, or maybe calling assoc
repeatedly.
I think it's doable, it would just be a little annoying to write.