2017-01-09 5 views
0

Я изучаю макросы с базовыми примерами, и я не понимаю, как это работает.Clojure: почему этот макрос не работает?

Это:

(defmacro evalf [f v] 
    (f v)) 
(evalf + 2) 

не работает.

Я пробовал:

(defmacro evalf [f v] 
    '(f v)) 
(evalf + 2) 

не повезло ...

Я не понимаю других синтаксисом: ~ ~ @ и так далее, но они не работают либо. Я вижу, что символ f не указывает на +, но я не знаю, чтобы сказать «принять значение f, которое равно +».

Можете ли вы прояснить ситуацию? Заранее спасибо

ответ

4

В зависимости от того, что вы хотите сделать, есть два варианта:

Сначала один (тот, который вы, вероятно, хотите) является:

(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, как в первом варианте.

+0

Спасибо, оба ответа, но я понял больше ваших, поэтому я выбрал это –

4

Попробуйте

(defmacro evalf [f v] 
    (list f v)) 

(evalf (partial * 2) 66); 132 

В зову evalf

  • аргументы проходят невычисленного в форм(partial * 2) и 66;
  • тело макроса дает выражение (list '(partial * 2) '66);
    • , которая вычисляется в виде ((partial * 2) 66)
    • , который, возвращаемой из макроса, вычисляется в 132.

Альтернативой, используя синтаксис квотирование, является

(defmacro evalf [f v] 
    `(~f ~v)) 
Смежные вопросы