Вычислить значение выражения и передать в макрос - Lisp
Формулировка задачи:
Пытаюсь разобраться с макросами, и всплыла любопытная задачка, которую я никак не могу решить:
1) Подсчитать значение некоторого выражения;
2) Передать это значение макросу;
3) Раскрыть макрос;
4) Выполнить код в текущем контексте.
Вот, например, я пытаюсь написать макрос print-sum, при раскрытии которого, код
преобразовывался бы в
Сделал кучу попыток, но ничего не получилось. Вот, например:
"Numberp" здесь используется только для того, чтобы проверить, что макрос на вход число получил. Нет, не получил... Внутри макроса переменная "x" равна "b", а не "2".
Следующая попытка:
Тоже не то. "Eval" вычисляется в toplevel, а переменная "b" локальна, она есть только в том контексте, из которого вызывается макрос.
Тогда, может, составить выражение в виде списка и вычислить его? Например, так:
Не работает. "Apply" и "funcall" не работают с макросами.
Но, у нас есть "cons":
Почти то, что нужно. С помощью "eval", лисп начинает вычислять значение выражения "(print-sum 2)", так что с переменной "b" мы разобрались. Но, "eval" вычисляет в toplevel, а переменная "a" у нас, тоже, локальна - получаем сообщение об ошибке.
Наугад попробовал несколько вариантов с "macrolet", например так:
Пишет, что я пытаюсь использовать не определённую функцию "print-sum" ("Error: Undefined function PRINT-SUM called with arguments (2) .").
В пределах моих, очень ограниченных, знаний, задача не решается. Это ограничение лиспа, или, всё-таки, есть какой-то способ её решения?
(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) )
(defmacro print-sum (x) (if (numberp (eval x)) `(princ (+ ,(eval x) a))) ) (let ((a 1) (b 2)) (print-sum b) )
(defmacro print-sum (x) (if (numberp (eval x)) `(princ (+ ,(eval x) a))) ) (let ((a 1) (b 2)) (apply 'print-sum (list b)) )
(defmacro print-sum (x) (if (numberp (eval x)) `(princ (+ ,(eval x) a))) ) (let ((a 1) (b 2)) (eval (cons 'print-sum (list b))) )
(let ((a 1) (b 2)) (macrolet ((print-sum (x) (if (numberp (eval x)) `(princ (+ ,(eval x) a))) )) (apply 'print-sum (list b)) ))
Решение задачи: «Вычислить значение выражения и передать в макрос»
textual
Листинг программы
(defmacro let! (args &body forms) `(compiler-let ,args (let ,args ,@forms)))
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д