Tenho uma macro para definir variáveis de inicialização para o programa. A macro é ...
(defmacro defparm (var value &key (frequency nil) (date nil date-supplied-p))
"Macro to define starting parameters."
`(let ((new-value (set-value ,value ,frequency)))
(cond ((eq ,date-supplied-p t)
(set-variation ',var new-value (make-date ,date)))
(t (setf (slot-value *my-parms* ',var) new-value)))))
Esta macro depende das macros set-value e set-variation e das funções is-date-p e is-percent-p.
(defun is-percent-p (value)
(cond ((and (symbolp value) (char= (char (symbol-name value) (1- (length (symbol-name value)))) #\%)))
((and (stringp value) (char= (char value (1- (length value))) #\%)))
(t nil)))
(defmacro set-value (value &optional frequency)
`(cond ((and (typep ',value 'symbol) (is-percent-p ',value))
(let ((new-value (string-right-trim "%" (symbol-name ',value))))
(/ (if (find #\. new-value)
(parse-float:parse-float new-value)
(parse-integer new-value :junk-allowed nil)) 100.0)))
(t ,value)))
Não incluí is-date-p porque não é relevante nessa situação, e set-variation pode ser simplesmente descartado...
(defun set-variation (&rest x)
(declare (ignorable x)))
Quando eu avalio...
(defparm interest-rate 5%)
Eu entendo isso...
(defparm interest-rate 5%) ; in: DEFPARM INTEREST-RATE ; (SET-VALUE 5% NIL) ; --> IF IF AND IF TYPEP ; ==> ; 1 ; ; pego AVISO: ; variável indefinida: COMMON-LISP-USER::5% ; ; unidade de compilação finalizada ; Variável indefinida: ; 5% ; pego 1 AVISO condição 0,05 0,05
O resultado está correto, 0,05, mas não entendo por que recebo o aviso.
Coloquei instruções (print nn) na tentativa de identificar onde o aviso ocorre, onde o símbolo '5%' é avaliado, mas não consigo encontrá-lo.
Onde no meu código está o ponto real do "aviso"?!
Se expandirmos sua expressão completamente ("andar"), teremos algo assim:
Você pode ver que no seu primeiro
cond
há uma cláusula(t 5%)
. É onde5%
está uma variável.Normalmente, eu depuraria essas coisas expandindo macros dos trechos de código correspondentes (e, opcionalmente, um compilador me daria localizações de variáveis indefinidas, etc.):
set-value
precisa chamaris-percent-p
no momento da macroexpansão, não colocar a chamada na expansão.