Given a list of names for variables, I want to set those variables to an expression.
I tried this:
(doall (for [x ["a" "b" "c"]] (def (symbol x) 666)))
...but this yields the error
java.lang.Exception: First argument to def must be a Symbol
Can anyone show me the right way to accomplish this, please?
In Clojure, variables are defined by the 'def' keyword. It's a bit different wherein the concept of variables has more to do with binding. In Clojure, a value is bound to a variable.
def is a special form that associates a symbol (x) in the current namespace with a value (7). This linkage is called a var . In most actual Clojure code, vars should refer to either a constant value or a function, but it's common to define and re-define them for convenience when working at the REPL.
Clojure let is used to define new variables in a local scope. These local variables give names to values. In Clojure, they cannot be re-assigned, so we call them immutable.
Clojure's "intern" function is for this purpose:
(doseq [x ["a" "b" "c"]]
(intern *ns* (symbol x) 666))
(doall (for [x ["a" "b" "c"]] (eval `(def ~(symbol x) 666))))
In response to your comment:
There are no macros involved here. eval
is a function that takes a list and returns the result of executing that list as code. ` and ~ are shortcuts to create a partially-quoted list.
` means the contents of the following lists shall be quoted unless preceded by a ~
~ the following list is a function call that shall be executed, not quoted.
So ``(def ~(symbol x) 666)is the list containing the symbol
def, followed by the result of executing
symbol xfollowed by the number of the beast. I could as well have written
(eval (list 'def (symbol x) 666))` to achieve the same effect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With