12

How do I avoid byte-compiler warnings Unused lexical variable in functions defined using macros expanding to defun?

E.g., macro defun-rcirc-command in rcirc.el uses the target variable which is not used by several invocations.

In Common Lisp I can use the ignorable declaration: (declare (ignorable target)).

Bad solutions:

  • Add something like (setq target target) to all the users of defun-rcirc-command which do not use target: that requires modifying many macro invocations.

  • Prefixing the ignorable variable with an underscore - _target - does not help because _ means ignore, not ignorable, i.e., when it is used, I get variable '_target' not left unused.

sds
  • 5,928
  • 20
  • 39

2 Answers2

15

The way I've done that so far is to add a call of the shape

(ignore <var>)

This function call will be optimized away, but before that the compiler will still count it as a use, so the "unused" warning won't be triggered.

Stefan
  • 26,154
  • 3
  • 46
  • 84
-1

Looking at the code, it appears that target is not intended to be a global variable but passed to the created function when it is called. If that is the case, it is better to create it as a symbol local to the macro. A simple example of a macro that creates a function that accepts an argument and adds 10 to it:

(defmacro xxx (name)  
  ""
  (let ((target (make-symbol "target")))
  `(defun ,name (,target) (+ 10 ,target))))

Calling

(xxx hamster)

will result in a function named hamster that accepts one argument.

Then you can call

(hamster 5)

and it will return 15.

The trick is to create a new symbol that will act as the argument to the new function.

EDIT:

I have always seen that if you are referring to the generated symbol in the passed in body expression, you include the name in the call like:

(defmacro xxx (name t2 &rest body)  
  ""
  (let ((t2-arg (make-symbol "target")))
  `(defun ,name (&optional ,t2-arg) 
     (let ((,t2 (or ,t2-arg 10)))
       ,@body))))

Which then turns the calls into:

(xxx hamster target (+ target 20))

where

(hamster)

which returns 30 and

(hamster 20)

returns 40.

Admittedly, this always bugs me when I write macros this way until I look at the usage in which it appears a parameter is declared and later used.

M Smith
  • 279
  • 1
  • 7
  • 2
    The body of the function is passed to the macro and it must be able to refer to `target`. IOW, your excellent suggestion is not applicable in this specific case. – sds Apr 16 '15 at 21:23