Вычислить значение выражения и передать в макрос - Lisp

Узнай цену своей работы

Формулировка задачи:

Пытаюсь разобраться с макросами, и всплыла любопытная задачка, которую я никак не могу решить: 1) Подсчитать значение некоторого выражения; 2) Передать это значение макросу; 3) Раскрыть макрос; 4) Выполнить код в текущем контексте. Вот, например, я пытаюсь написать макрос print-sum, при раскрытии которого, код
(let ((a 1) (b 2))
 (print-sum b)
)
преобразовывался бы в
(let ((a 1) (b 2))
 (princ (+ 2 a)
)
Сделал кучу попыток, но ничего не получилось. Вот, например:
(defmacro print-sum (x)
 (if (numberp x) `(princ (+ ,x a)))
)
 
(let ((a 1) (b 2))
 (print-sum b)
)
"Numberp" здесь используется только для того, чтобы проверить, что макрос на вход число получил. Нет, не получил... Внутри макроса переменная "x" равна "b", а не "2". Следующая попытка:
(defmacro print-sum (x)
 (if (numberp (eval x)) `(princ (+ ,(eval x) a)))
)
 
(let ((a 1) (b 2))
 (print-sum b)
)
Тоже не то. "Eval" вычисляется в toplevel, а переменная "b" локальна, она есть только в том контексте, из которого вызывается макрос. Тогда, может, составить выражение в виде списка и вычислить его? Например, так:
(defmacro print-sum (x)
 (if (numberp (eval x)) `(princ (+ ,(eval x) a)))
)
 
(let ((a 1) (b 2))
 (apply 'print-sum (list b))
)
Не работает. "Apply" и "funcall" не работают с макросами. Но, у нас есть "cons":
(defmacro print-sum (x)
 (if (numberp (eval x)) `(princ (+ ,(eval x) a)))
)
 
(let ((a 1) (b 2))
 (eval (cons 'print-sum (list b)))
)
Почти то, что нужно. С помощью "eval", лисп начинает вычислять значение выражения "(print-sum 2)", так что с переменной "b" мы разобрались. Но, "eval" вычисляет в toplevel, а переменная "a" у нас, тоже, локальна - получаем сообщение об ошибке. Наугад попробовал несколько вариантов с "macrolet", например так:
(let ((a 1) (b 2))
 (macrolet
  ((print-sum (x)
    (if (numberp (eval x)) `(princ (+ ,(eval x) a)))
  ))
  (apply 'print-sum (list b))
))
Пишет, что я пытаюсь использовать не определённую функцию "print-sum" ("Error: Undefined function PRINT-SUM called with arguments (2) ."). В пределах моих, очень ограниченных, знаний, задача не решается. Это ограничение лиспа, или, всё-таки, есть какой-то способ её решения?

Решение задачи: «Вычислить значение выражения и передать в макрос»

textual
Листинг программы
(defmacro let! (args &body forms)
  `(compiler-let ,args
     (let ,args
       ,@forms)))

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 3.727 из 5
Похожие ответы