2008-09-13 4 views
5

Я работаю через Practical Common Lisp и в качестве упражнения решил написать макрос, чтобы определить, является ли число кратным другой номер:Мой первый макрос Lisp; он протекает?

(defmacro multp (value factor)
`(= (rem ,value ,factor) 0))

так, что: (multp 40 10) оценивается как истина в то время как (multp 40 13) не

Вопрос в том, что это макрос leak в некотором роде? Также этот «хороший» Лисп? Есть ли уже существующая функция/макрос, которую я мог бы использовать?

ответ

11

Siebel дает обширное изложение (для простых случаев в любом случае) возможных источников утечек, и их здесь нет. Оба value и factor оцениваются только один раз и в порядке, а rem не имеет побочных эффектов.

Это не очень хорошо Lisp, хотя в этом случае нет причин использовать макрос. A

(defun multp (value factor) 
    (zerop (rem value factor))) 

идентичен для всех практических целей. (Обратите внимание на использование zerop.Я думаю, что в этом случае это делает все более ясным, но в тех случаях, когда вам нужно подчеркнуть, что тестируемое значение может по-прежнему иметь смысл, если это что-то другое, кроме нуля, (= ... 0) может быть лучше)

+0

Это большое спасибо. Любая идея о требованиях для простого оправдаемого макроса для создания в качестве упражнения тогда? – 2008-09-13 04:33:46

2

Ваш макрос хорошо выглядит для меня. Я не знаю, что такое протекающий макрос, но ваш довольно простой и не требует каких-либо gensyms. Если это «хороший» Lisp, мое правило состоит в том, чтобы использовать макрос только тогда, когда функция не будет работать, и в этом случае вместо вашего макроса можно использовать функцию. Однако, если это решение работает для вас, нет причин не использовать его.

1

Ну, в принципе, пользователь может сделать это:

(flet ((= (&rest args) nil)) 
    (multp 40 10)) 

, который будет оценивать всухую ... за исключением того, что ANSI CL делает его незаконным пересвязать большинство стандартных символов, в том числе CL: =, так что вы в этом конкретном случае.

В общем случае вы должны знать как ссылочную непрозрачность (захват идентификаторов из контекста, в котором макрос расширяется), так и макрос негигиены (утечка идентификаторов в расширенный код).

0

Нет, символ, введенный в «лексическое закрытие» макроса, не выходит наружу.

Обратите внимание, что утечка не является ОБЯЗАТЕЛЬНО плохой, даже если случайная утечка почти всегда есть. Для одного проекта я работал, я обнаружил, что макрос похож на это было полезно:

(defmacro ana-and (&rest forms) 
    (loop for form in (reverse forms) 
     for completion = form then `(let ((it ,form)) 
             (when it 
             ,completion)) 
     finally (return completion))) 

Это позволило мне получить «короткое замыкание» вещей, необходимых должно быть сделано в последовательности, с аргументами, перенесенных из предыдущего вызовы в последовательности (и отказ, вызванный возвратом NIL). Конкретный контекст этого кода есть для рукописного анализатора для файла конфигурации, который имеет синтаксис с мощным буфером, достаточным для написания правильного парсера с использованием генератора синтаксического анализатора, больше работы, чем ручной перемотки.

Смежные вопросы