Pergunta

Eu tenho trabalhado Lisp comum prático e como exercício decidi escrever uma macro para determinar se um número é múltiplo de outro número:

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

para que :(multp 40 10)avalia como verdadeiro enquanto(multp 40 13)não

A questão é: esta macro vazar de algum modo?Além disso, esse Lisp é "bom"?Já existe uma função/macro que eu poderia ter usado?

Foi útil?

Solução

Siebel fornece um extenso resumo (pelo menos para casos simples) de possíveis fontes de vazamentos, e não há nenhuma delas aqui.Ambos value e factor são avaliados apenas uma vez e em ordem, e rem não tem efeitos colaterais.

Porém, isso não é um bom Lisp, porque não há razão para usar uma macro neste caso.Uma função

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

é idêntico para todos os efeitos práticos.(Observe o uso de zerop.Acho que isso deixa as coisas mais claras neste caso, mas nos casos em que você precisa destacar que o valor que você está testando ainda pode ser significativo se for algo diferente de zero, (= ... 0) pode ser melhor)

Outras dicas

Sua macro parece boa para mim.Não sei o que é uma macro com vazamento, mas a sua é bastante direta e não requer gensyms.No que diz respeito a se isso for Lisp "bom", minha regra geral é usar uma macro somente quando uma função não funcionar e, nesse caso, uma função pode ser usada no lugar de sua macro.No entanto, se esta solução funcionar para você, não há razão para não usá-la.

Bem, em princípio, um usuário poderia fazer isto:

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

que seria avaliado como NIL ...exceto que ANSI CL torna ilegal religar a maioria dos símbolos padrão, incluindo CL:=, então você está no lado seguro neste caso específico.

Em geral, é claro, você deve estar ciente tanto da falta de transparência referencial (captura de identificadores do contexto em que a macro é expandida) quanto da falta de higiene da macro (vazamento de identificadores para o código expandido).

Não, nenhum símbolo introduzido no “fechamento lexical” da macro é liberado para o exterior.

Observe que o vazamento não é NECESSARIAMENTE uma coisa ruim, mesmo que o vazamento acidental quase sempre seja.Para um projeto em que trabalhei, descobri que uma macro semelhante a esta era útil:

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

Isso me permitiu obter um "curto-circuito" de coisas que precisavam ser feitas em sequência, com argumentos transportados de chamadas anteriores na sequência (e uma falha sinalizada pelo retorno de NIL).O contexto específico de origem deste código é para um analisador escrito à mão para um arquivo de configuração que possui uma sintaxe remendada o suficiente para que escrever um analisador adequado usando um gerador de analisador fosse mais trabalhoso do que rolar manualmente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top