I'm finding myself writing a function that passes every variable bound in the enclosing let expression. The simplified form of this scenario, in psuedocode, is
(let [a 1 b 2 c 3 d 4 e 5 f 6]
(do-something a b c d)
(f a b c d e f g)
(compute-another-thing a c))
whereas I want to write something more like...
(let env-name [a 1 b 2 c 3 d 4 e 5 f 6]
(do-something (take 4 env-name))
(f env-name)
(compute-another-thing a c))
That is, does the clojure core (or something external and reliable) provide a let
variant that gathers all bindings into a collection with a name?
Destructuring will get you part of the way there:
(let [[a b c d e f :as env-name] [1 2 3 4 5 6]]
(apply do-something (take 4 env-name))
(apply f env-name)
(compute-another-thing a c))
Note you have to use apply when calling functions using env-name.
For something more elegant (like your proposed form), I think you would have to write your own macro.
Update: Here's a (very-lightly tested) macro that can handle simple cases:
(defmacro let-as
[as-bind-name bindings & body]
(let [lhs-bindings (map first (partition 2 bindings))]
`(let ~bindings
(let [~as-bind-name [~@lhs-bindings]]
~@body))))
This should do what you want so long as the left-hand side of your normal let-bindings are simple symbols (ie don't use destructuring).
Some REPL interactions to illustrate:
core> (let-as env-name [a 1 b 2 c 3 d 4 e 5 f 6] (print env-name) (apply + env-name))
[1 2 3 4 5 6]
21
Some destructuring is well-behaved:
core> (let-as env-name [[a b] [1 2] [c d] [3 4]] (print env-name) (map first env-name))
[[1 2] [3 4]]
(1 3)
Other destructuring is not:
core> (let-as env-name [{:keys [a b]} {:a 1 :b 2}] (print env-name) (+ a b))
[{:keys [1 2]}]
3
This could be remedied, but the macro would have to be more complex