Как определить функцию из строки в Clojure?

Я хотел бы сделать это (в REPL или в любом месте)

(defn (symbol "print-string") [k] (println k))

а затем можно сделать

(print-string "lol")

Или, если есть какой-либо другой способ создать defn из пользовательских строк в макросах, можете ли вы подтолкнуть меня в правильном направлении?

Ответы

Ответ 1

(defmacro defn-with-str [string args & body]
 `(defn ~(symbol string) ~args [email protected]))

(defn-with-str "print-string" [k] (println k))

(print-string "lol")

Ответ 2

dnolen solution работает в момент макрорасширения, Брайан Карпер во время чтения. Теперь, здесь один для времени выполнения:

(intern *ns* (symbol "a") (fn [k] (println k)))

Ответ 3

Мне нравится dnolen answer better, но вы тоже можете это сделать:

(defn #=(symbol "print-string") [k] (println k))

#=() оценивается во время чтения. Я не знаю, насколько стабильной является функция Clojure, я бы не стал полагаться на нее, чтобы она не изменилась в будущем. Макросы - это то, как я это сделаю.

Ответ 4

FYI - dnolen ответ будет работать только для буквенных строк, а не для строк в переменных def'd или let'd.

(defmacro defn-with-str [string args и body]  `(defn ~ (символьная строка) ~ args ~ @body))

(def hisym "привет" ) (defn-with-str hisym [] (println "hi" ))

Теперь у вас есть функция, называемая "hisym"

(hi) → java.lang.Exception: невозможно разрешить символ: привет в этом контексте (NO_SOURCE_FILE: 6) (hisym) → печатает "привет"

Чтобы избежать этого, eval строку имени функции в макросе

(defmacro defn-with-str [string args & body]
`(defn ~(symbol (eval string)) ~args [email protected]))