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

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

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

а потом уметь делать

(print-string "lol")

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


person mannicken    schedule 24.03.2009    source источник


Ответы (4)


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

(intern *ns* (symbol "a") (fn [k] (println k)))
person Matthias Benkard    schedule 24.03.2009
comment
Круто не знал об этом. Одно предостережение заключается в том, что в var a будут отсутствовать метаданные функции, которые вы получаете при использовании defn. - person dnolen; 25.03.2009

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

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

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

person Brian Carper    schedule 24.03.2009

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

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

(def hisym "hi") (defn-with-str hisym [] (println "hi"))

Теперь у вас есть функция под названием «hisym».

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

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

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

person Community    schedule 10.03.2010

person    schedule
comment
1. Что такое ~ перед аргументами? 2. Что такое ~@ перед body? - person Belun; 08.09.2010
comment
@Белун 1. ~ = без кавычек 2.~@ = развернуть последовательность - person Surya; 13.09.2010
comment
почему если я делаю (defn defns [] (doall (map (fn [s] (defn-with-str s [k] (println k))) [print-string]))) я получаю fn с именем 'с'? - person Hendekagon; 16.05.2012
comment
Макросы @Hendekagon не являются обычными функциями - person dnolen; 16.05.2012