Макросы для генерации функций
Я пытаюсь написать несколько макросов для программирования ограничений на целые числа и, в частности, я пытаюсь расширить
(int-constr (x y z)
(< 10
(+
(* x 4)
(* y 5)
(* z 6)))
(> 10
(+
(* x 1)
(* y 2)
(* z 3))))
в
(let ((x (in-between 0 1))
(y (in-between 0 1))
(z (in-between 0 1)))
(assert
(and (< 10
(+
(* x 4)
(* y 5)
(* z 6)))
(> 10
(+
(* x 1)
(* y 2)
(* z 3)))))
(list x y z))
При рекурсивном использовании синтаксических правил я могу создавать вложенные let в начале, но я думаю, что теряю возможность вызова списка аргументов в конце. Есть ли способ сделать это?
1 ответ
Решение
Даже просто придерживаясь syntax-rules
этот макрос легко написать с помощью эллипсов. Вот реализация описанного вами поведения:
(define-syntax int-constr
(syntax-rules ()
((_ (x ...) constr ...)
(let ((x (in-between 0 1)) ...)
(assert (and constr ...))
(list x ...)))))
Поскольку эллипсы можно использовать для повторения форм, содержащих переменные шаблона, а не просто для повторения простых переменных шаблона самостоятельно, этот макрос довольно декларативен, и его легко читать и писать.