Как определить функцию из строки в Clojure? - PullRequest
15 голосов
/ 24 марта 2009

Я бы хотел сделать это (в REPL или где-либо еще)

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

и тогда сможете сделать

(print-string "lol")

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

Ответы [ 4 ]

22 голосов
/ 25 марта 2009
(defmacro defn-with-str [string args & body]
 `(defn ~(symbol string) ~args ~@body))

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

(print-string "lol")
17 голосов
/ 25 марта 2009

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

(intern *ns* (symbol "a") (fn [k] (println k)))
14 голосов
/ 25 марта 2009

Мне больше нравится ответ Днолена, но вы тоже можете сделать это:

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

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

7 голосов
/ 10 марта 2010

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

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

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

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

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

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

(defmacro defn-with-str [string args & body]<br/> `(defn ~(symbol (eval string)) ~args ~@body))

...