Определить макрос для цикла с параметром for - Lisp
Формулировка задачи:
Определите макрос для цикла с параметром for, реализующий итерационный процесс через вызов функции с хвостовой рекурсией. Формат команды для вызова макроса:
(for ((parameter-1 start-value-1) ... (parameter-k start-value-k)) (continue-expr cont-body) body)
гдеparameter-1 – parameter-k
— идентификаторы — параметры цикла;start-value-1 – start-value-k
— начальные значения параметров цикла;continue-expr
—условие выполнения цикла;cont-body
—одно или несколько выражений, которые выполняются после каждой итерации (перед проверкой условия continue-expr);body
— тело цикла—одно или несколько выражений. Результат выполнения макроса—значение последнего выражения в теле body.Решение задачи: «Определить макрос для цикла с параметром for»
textual
Листинг программы
(defmacro for (e1 (e3 e4) &body e2) (let ((func-name (gensym)) (res (gensym)) (con (gensym))) `(let ,e1 (let ((,res (progn ,@e2)) (,con (progn ,e4 ,e3))) (labels ((,func-name (,res ,con) (if ,con (,func-name (prog1 (progn ,@e2) ,e4) ,e3) ,res))) (,func-name ,res ,con))))))
Объяснение кода листинга программы
В данном коде определен макрос for, который предназначен для создания цикла с параметром for. Макрос имеет следующую структуру:
(defmacro for (e1 (e3 e4) &body e2) ...)- определение макросаforс тремя обязательными аргументами:e1,e3иe4, а также необязательным списком аргументовe2.(let ((func-name (gensym)) (res (gensym)) (con (gensym))) ...)- начало тела макроса, где создаются три вспомогательные переменные:func-name,resиcon.(labels ((,func-name (,res ,con) ...))- определение анонимной функции с именемfunc-name, которая принимает два аргумента:resиcon.(,func-name ,res ,con)- вызов анонимной функции с передачей значенийresиconв качестве аргументов.(,func-name (prog1 (progn ,@e2) ,e4) ,e3)- вызов анонимной функцииfunc-nameс передачей результатов выполнения списка выраженийe2иe4в качестве аргументов, а также передачей значенияe3.(if ,con ...)- проверка условияcon, если оно истинно, то выполняется выражение внутри блокаif, иначе выполняется следующее выражение.(,res)- возвращение значения переменнойresиз анонимной функции.(,func-name ,res ,con))- повторный вызов анонимной функции с передачей значенийresиconв качестве аргументов.(,func-name ,res ,con))- еще один повторный вызов анонимной функции с передачей значенийresиconв качестве аргументов....)- конец тела макроса. Таким образом, данный код определяет макросfor, который позволяет создавать цикл с параметромfor. Макрос принимает три обязательных аргумента и необязательный список аргументов, создает три вспомогательные переменные и использует их для выполнения цикла.