Reputation: 2433
I defined this macro:
(defmacro with-current-directory (directory &rest body)
"Set the working directory temporarily set to DIRECTORY and run BODY.
DIRECTORY is expanded"
`(let ((default-directory
,(file-name-as-directory
(expand-file-name (eval directory)))))
,@body))
which I use in some lisp functions that are loaded when emacs opens. I always get these warnings:
Eager macro-expansion failure: (void-variable repo-dir)
Eager macro-expansion failure: (wrong-type-argument stringp nil)
Which I understand is happening because those variables are not defined at load time, and emacs is trying to eval them. My question is, how do I avoid getting these warnings. Is there a way to define the macro so that doesn't happen? I cannot figure out how to use the value of the variable, and not the symbol for the variable itself.
Upvotes: 6
Views: 6305
Reputation: 41568
Like this:
`(let ((default-directory
(file-name-as-directory (expand-file-name ,directory))))
Since directory
is not the value, but the lisp expression that would evaluate to the value, you need to insert (using the comma operator) the expression into the expansion of the macro. If you put the comma before the call to file-name-as-directory
, you would have to be able to compute the directory at macro expansion time based only on the tokens of the expression, which you can't do if directory
refers to a variable name.
Upvotes: 7
Reputation: 4029
Looks like some beat me to it. Look at the other answer.
You should not be evaluating the file name expansion at expansion time. Also the eval call should not be there. The only thing that should happen during macro expansion is placing the value of directory inside the returned expression. Remove eval and place your comma in front of directory.
It's nice to know that anytime you're using eval, you're probably doing something wrong
Upvotes: 1