В зависимости от того, что вы хотите сделать, есть два варианта:
Сначала один (тот, который вы, вероятно, хотите) является:
(defmacro evalf [f v] `(~f ~v))
или
(defmacro evalf [f v] (list f v))
Оба они делают то же самое: сгенерируйте s-выражение, которое вам нужно. С этим (evalf + 10)
будет расширен до (+ 10)
во время компиляции, а затем успешно оценен во время выполнения.
Второй один такой:
(defmacro evalf [f v] ((resolve f) v))
Теперь функция f
будет называется во время компиляции, поэтому макрос будет расширен в результате: 10
Ваш вариант с (f v)
неудавшейся молча , потому что когда вы вызываете (evalf + 10)
, +
здесь просто обычный символ, а не ссылка на функцию с точки зрения макроса, поэтому он пытается вызвать ('+ 10)
, поскольку символ в clojure имеет семантику функции, это абсолютно правильный синтаксис, но этот вызов вызывает nil
. (пример вызова символа: ('+ {'+ 10})
=> 10) Итак, если вы хотите получить функцию, названную как этот символ, вам придется ее решить, как в моем втором примере.
А вариант с '(f v)
только расширяется список из двух символов: 'f
и 'v
, а затем приводит к исполняемым вызова ('f 'v)
, который также возвращает nil
, как в первом варианте.
Спасибо, оба ответа, но я понял больше ваших, поэтому я выбрал это –