Pregunta

he estado trabajando a través de Ceceo común práctico y como ejercicio decidí escribir una macro para determinar si un número es múltiplo de otro número:

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

de modo que :(multp 40 10)se evalúa como verdadero mientras(multp 40 13)no es

La pregunta es ¿esta macro filtración ¿de alguna manera?¿También es este Lisp "bueno"?¿Existe ya una función/macro que podría haber usado?

¿Fue útil?

Solución

Siebel ofrece un resumen extenso (al menos para casos simples) de posibles fuentes de fugas, y no hay ninguna de ellas aquí.Ambos value y factor se evalúan sólo una vez y en orden, y rem no tiene ningún efecto secundario.

Sin embargo, este no es un buen Lisp, porque no hay razón para usar una macro en este caso.Una función

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

es idéntico a todos los efectos prácticos.(Tenga en cuenta el uso de zerop.Creo que aclara las cosas en este caso, pero en los casos en los que necesitas resaltar que el valor que estás probando aún podría ser significativo si es algo distinto de cero, (= ... 0) podría ser mejor)

Otros consejos

Tu macro me parece bien.No sé qué es una macro con fugas, pero la tuya es bastante sencilla y no requiere ningún gensyms.En cuanto a si este es un Lisp "bueno", mi regla general es usar una macro sólo cuando una función no funciona, y en este caso se puede usar una función en lugar de su macro.Sin embargo, si esta solución funciona para usted, no hay razón para no utilizarla.

Bueno, en principio un usuario podría hacer esto:

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

que se evaluaría como NIL...excepto que ANSI CL hace que sea ilegal volver a vincular la mayoría de los símbolos estándar, incluido CL:=, por lo que está en el lado seguro en este caso particular.

En general, por supuesto, debe tener en cuenta tanto la falta de transparencia referencial (capturar identificadores del contexto en el que se expande la macro) como la falta de higiene de la macro (filtrar identificadores al código expandido).

No, ningún símbolo introducido en el "cierre léxico" de la macro se libera al exterior.

Tenga en cuenta que las fugas no son NECESARIAMENTE algo malo, incluso si las fugas accidentales casi siempre lo son.Para un proyecto en el que trabajé, encontré que una macro similar 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)))

Esto me permitió "cortocircuitar" las cosas que debían hacerse en secuencia, con argumentos transferidos de llamadas anteriores en la secuencia (y una falla señalada al devolver NIL).El contexto específico del que proviene este código es para un analizador escrito a mano para un archivo de configuración que tiene una sintaxis lo suficientemente improvisada como para que escribir un analizador adecuado usando un generador de analizadores fuera más trabajo que hacerlo manualmente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top