Quero demonstrar minha falta de conhecimento com um exemplo.
Usando as duas definições de macro a seguir,
(defmacro for (var from init to final do &rest body)
"Execute a simple for loop: (for i from 1 to 10 do (print i))."
(let ((tempvar 'max))
`(let ((,var ,init)
(,tempvar ,final))
(while (<= ,var ,tempvar)
,@body
(setq ,var (1+ ,var))))))
(defmacro for (var from init to final do &rest body)
"Execute a simple for loop: (for i from 1 to 10 do (print i))."
(let ((tempvar (make-symbol "max")))
`(let ((,var ,init)
(,tempvar ,final))
(while (<= ,var ,tempvar)
,@body
(setq ,var (1+ ,var))))))
a primeira macro oculta todas as variáveis nomeadas max
que podem ocorrer no corpo e a segunda não, o que pode ser mostrado com o seguinte exemplo:
(let ((max 0)) ;; this variable is shadowed if the first macro defintion is used
(for i from 1 to 3 do
(setq square (* i i))
(if (> square max)
(princ (format "\n%d %d" i square)))))
Tanto quanto eu aprendi, a avaliação de uma chamada macro funciona assim:
A macro é avaliada duas vezes. Primeiro, o corpo é avaliado e retorna um formulário. Este formulário é avaliado novamente.
Por enquanto, tudo bem.
Mas se eu presumir que a macro realmente retorna um pedaço de texto que, por acaso, é uma forma lisp, que depois é interpretada, eu recebo um conflito que me torna incapaz de entender o exemplo acima.
Que parte do texto make-symbol
retorna a segunda macro que usa , para que não ocorra sombra? No meu entendimento, um nome de símbolo escolhido aleatoriamente extremamente improvável faria sentido.
Se eu usar as pp-macroexpand...
duas macros, retorne a mesma expansão.
Alguém é capaz de me ajudar a sair dessa confusão?
print-gensym
e print-circle
para t
você, poderá ver a diferença nas expansões de macro.
#:max
. O que isso significa ? Estou muito interessado em mais detalhes.
#:
é apenas uma convenção da impressora para indicar um símbolo uninterned (isto é o que print-gensym
se acende), não há mais detalhes no manual: (elisp) Creating Symbols
.