Une utilisation obligatoire de eval-when
consiste à s'assurer que les fonctions dont dépend une macro sont disponibles au moment de la compilation et de l'utilisation de la macro. Cependant, je ne peux pas penser à un exemple qui démontrerait les conséquences de ne pas utiliser eval-when
.En Common Lisp, quand avez-vous besoin d'utiliser eval-when, et comment le savez-vous?
(defpackage :eval-when
(:use :cl))
(in-package :eval-when)
(defun util-fun (x) (* x x))
(defmacro needs-help (x) `(let ((a (util-fun ,x))) a))
;; use it in the same file
(defun use-the-macro (x) (needs-help x))
(use-the-macro 5)
Si je comprends bien, le (defun util-fun ...)
doit être enveloppé avec eval-when
.
EDIT:Comme vous le verrez dans la réponse, il y a un problème avec cet exemple: il n'appelle pas réellement UTIL-FUN au moment de la compilation. Ceci explique pourquoi aucune erreur n'est donnée, car ce n'est pas une erreur. Mais la question est toujours valable en ce qu'elle met en évidence la confusion d'un nouvel utilisateur.
Cependant, à partir du REPL, aucune erreur ou un avertissement est émis lors de la compilation, la charge ou l'utilisation (SBCL 1.3.20):
; SLIME 2.19
CL-USER> (uiop:getcwd)
#P"/home/anticrisis/dev/common-lisp/eval-when/"
CL-USER> (compile-file "eval-when.lisp")
; compiling file "/home/anticrisis/dev/common-lisp/eval-when/eval-when.lisp" (written 14 AUG 2017 11:30:49 AM):
; compiling (DEFPACKAGE :EVAL-WHEN ...)
; compiling (IN-PACKAGE :EVAL-WHEN)
; compiling (DEFUN UTIL-FUN ...)
; compiling (DEFMACRO NEEDS-HELP ...)
; compiling (DEFUN USE-THE-MACRO ...)
; compiling (USE-THE-MACRO 5)
; /home/anticrisis/dev/common-lisp/eval-when/eval-when.fasl written
; compilation finished in 0:00:00.009
#P"/home/anticrisis/dev/common-lisp/eval-when/eval-when.fasl"
NIL
NIL
CL-USER> (in-package :eval-when)
#<PACKAGE "EVAL-WHEN">
EVAL-WHEN> (use-the-macro 3)
; Evaluation aborted on #<UNDEFINED-FUNCTION USE-THE-MACRO {10035E1103}>.
EVAL-WHEN> (needs-help 4)
; Evaluation aborted on #<UNDEFINED-FUNCTION UTIL-FUN {100387FE33}>.
EVAL-WHEN> (load "eval-when.lisp")
T
EVAL-WHEN> (use-the-macro 3)
9
EVAL-WHEN> (needs-help 4)
16
EVAL-WHEN>
Notez que normalement j'utilise Cc Ck eval et charger un fichier à la réplique, mais ici, j'utilise les commandes compile-file
et load
pour démontrer qu'aucune erreur ne se produit. (Je reçois une erreur lorsque je tente d'utiliser les fonctions après leur compilation, mais avant qu'ils ne soient chargés, mais qui surviendrait avec un code à vide.)
Il y a des questions et des commentaires antérieurs qui se rapportent à ceci:
Ce previous StackOverflow answer semble dire très clairement que toute fonction qui est utilisée par une macro doit être entouré par la forme
eval-when
, ou chargé dans un fichier séparé.Ce commentaire de coredump est aussi très clair:
Lorsque la macro est étendue, toute fonction que les appels macro doivent être définis . Si vous avez une unité de compilation qui définit une macro, laquelle appelle des fonctions, mais que vous n'utilisez pas réellement la macro dans la même unité de compilation , vous n'avez pas besoin d'une évaluation. Si toutefois vous définissez un aux. fonction, une macro et que vous voulez utiliser votre macro dès que vous le définissez, alors l'implémentation pourrait se plaindre que l'aux. fonction est inconnue - coredump
Étant donné que, pourquoi mon exemple ne génère pas une erreur? Mon exemple va-t-il échouer sous d'autres scénarios? Un exemple d'erreur de compilation, de temps de chargement ou d'exécution générée en cas d'échec de l'utilisation correcte de eval-when
serait utile à ma compréhension.
Nous vous remercions pour votre patience!
Vous voudrez peut-être consulter cette question https://stackoverflow.com/questions/10674650/eval-when-uses. Vous pouvez également lire la section eval-when dans PCL http://www.gigamonkeys.com/book/the-special-operators.html –
@DavidHodge Merci pour la référence; J'ai élargi ma question pour être plus précis. – anticrisis
L'autre réponse que vous avez mentionnée parle de la compilation d'un fichier. Vous mentionnez un REPL. Ce sont deux choses différentes. S'il vous plaît également poster une question spécifique, mieux avec le code. –