Reputation: 1852
So I want to pass a function to the "name" portion of def. The problem is: "First argument to def must be a Symbol"
I'm trying to for instance do:
(def serverNumber 5)
(def (str "server" serverNumber) {:id serverNumber :value 4939})
But I can't find annnnnnny way to do this. Any help would be beyond appreciated :)
Upvotes: 3
Views: 68
Reputation: 15759
The run-time equivalent of def
is intern
:
(intern *ns*
(symbol (str "server" server-number))
{:id server-number :value 4939})
Upvotes: 1
Reputation: 33019
First, I have to note that this seems like a bad idea. Why are you trying to generate def
s with dynamically-generated names? (As @pst already pointed out, maps are the usual solution for creating bindings with dynamically-generated identifiers.)
Assuming you have a legit reason for doing this (maybe it's part of some library functionality where you're generating defs for the user), you can accomplish this with a macro:
(defmacro def' [sym-exp & other-args]
`(def ~(-> sym-exp eval symbol) ~@other-args))
(def serverNumber 5)
(def' (str "server" serverNumber) {:id serverNumber :value 4939})
Note that this only works at the top level (since macros are run at compile time). If you want to do this in a function or something then you just need to use eval:
(defn def'' [sym-exp & other-args]
(eval `(def ~(-> sym-exp eval symbol) ~@other-args)))
If you just want to create a bunch of agents, maybe something like this will work:
(def servers
(vec (for [i (range 5)]
{:id i :value 4939})))
Then you can just access them by index:
(servers 0)
; => {:id 0, :value 4939}
Upvotes: 3