Destruction of a constrained variational function: impossible?
Until now, I have always believed that whatever you can do in the binding let
, you can do in the argument vector for the form defn
.
However, I just noticed this - if I do it with a bind let
, it works:
(let [[x & more :as full-list] (range 10)]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
; x: 0
; more: (1 2 3 4 5 6 7 8 9)
; full list: (0 1 2 3 4 5 6 7 8 9)
But if I try to output it to a function, I get an exception:
(defn foo [x & more :as full-list]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
; CompilerException java.lang.RuntimeException: Unexpected parameter, compiling:(/tmp/form-init615613631940782255.clj:1:1)
It should be noted that this works:
(defn foo [[x & more :as full-list]]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
But then I have to pass the argument as a collection i.e. (foo [1 2 3])
...
Is it possible to define a function that takes a variable number of arguments and bind the entire group of arguments to a local variable without using the binding let
internally? It seems strange to me that you can't just do (defn foo [x & more :as full-list] ...
it. Is there any special reason why this doesn't work (or shouldn't)?
source to share
If you want a variable number of arguments, you don't see &:
(defn foo [& [x & more :as full-list]]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
Clojure's parameter definition has only one special case, which is &
char to indicate the variational number of arguments. The rest are simple simple arguments.
Now every simple argument can be destroyed using map or list syntax. For example:
(defn foo [ x y ] ...)
Can be destroyed as:
(defn foo [[x1 x2 & x-more :as x] {:keys [y1 y2 y3]}] ...)
So we say that we expect the first parameter to be a list of at least 2 items, and the second parameter is a map with some keys. Note that this will still be a two-parameter fn and that Clojure will not enforce that x actually has at least two elements. If x is an empty list, x1 and x2 will be nil.
Going back to your question, if you look at my answer, you can see that my fn has 0 required parameters with variable number of arguments, and the one you have has 1 required parameter with variable number of arguments. What I am doing is just destroying var arg.
source to share