If you want to do it on your own, you could use macros to extend the language in your own library. This is a limited way, although it does not recursively walk the forms and fully replace let
; you have to use it in lieu of let if you want to enable :rest forms. There are ways to code-walk and expand using macro tooling (like macrolet and other stuff), but that is an exercise for the reader. Quality Assurance notified me that they didn't have any time to test this outside of the immediate repl output you see, so user beware.
(defmacro fancy-let [bindings & body]
(let [binds (partition-all 2 bindings)
_ (assert (every? #(= 2 (count %)) binds) "binding form must be even yo!")]
`(let [~@(->> (for [[l r :as b] binds]
(if (and (map? l)
(l :rest)
(or (l :keys) (l :syms) (l :strs)))
(let [ks (l :keys)
strs (l :strs)
syms (l :syms)
remaining (l :rest)
selected (concat (map keyword ks)
(map name strs)
(for [s syms]
`(quote ~s)))
symb (gensym "the-map")]
[symb r
(dissoc l :rest) symb
remaining `(dissoc ~symb ~@selected)])
b))
(reduce (fn [acc xs] (apply conj acc xs)) []))]
~@body)))
user> (fancy-let [{:keys [a] :strs [name age] :syms [origin] :rest m}
{:a 1 :b 2 :c 3 "name" "bilbo" "age" 200 'origin :shire}]
{:a a :name name :age age :origin origin :remaining m})
{:a 1, :name "bilbo", :age 200, :origin :shire, :remaining {:b 2, :c 3}}