How to defn a function from string in Clojure?
-
21-08-2019 - |
Question
I'd like to do this (in REPL or anywhere)
(defn (symbol "print-string") [k] (println k))
and then be able to do
(print-string "lol")
Or, if there is any other way to create defn from custom strings in macroses, could you push me into the right direction please?
Solution
(defmacro defn-with-str [string args & body]
`(defn ~(symbol string) ~args ~@body))
(defn-with-str "print-string" [k] (println k))
(print-string "lol")
OTHER TIPS
dnolen's solution works at macro expansion time, Brian Carper's at read-time. Now, here's one for run-time:
(intern *ns* (symbol "a") (fn [k] (println k)))
I like dnolen's answer better, but you can do this too:
(defn #=(symbol "print-string") [k] (println k))
#=()
is evaluated at read-time. I don't know how stable a feature of Clojure this is, I wouldn't rely on it not to change in the future. Macros are how I'd do it.
FYI - dnolen's answer will only work for literal strings, and not for strings in def'd or let'd variables.
(defmacro defn-with-str [string args & body] `(defn ~(symbol string) ~args ~@body))
(def hisym "hi") (defn-with-str hisym [] (println "hi"))
You now have a function called "hisym"
(hi) -> java.lang.Exception: Unable to resolve symbol: hi in this context (NO_SOURCE_FILE:6) (hisym) -> prints "hi"
To avoid this, eval the function name string in the macro
(defmacro defn-with-str [string args & body]
`(defn ~(symbol (eval string)) ~args ~@body))