[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Reviving an old discussion about IGNORE

Most Lisp compilers a sociable and give a warning when
a lexical variable is not used. CommonLisp provides an
IGNORE declaration to keep the compiler quiet in such
instances. In Genera, there are four ways of accomplishing
this task, only one of which is supported by CommonLisp.

The first method:

(defun FOO (x y)
 (declare (ignore y))
 (bar x))

The second method:

(defun FOO (x ignore)
 (bar x))

The third method:

(defun FOO (x y)
 (ignore y)
 (bar x))

The fourth method:

(defun FOO (x y)
 y                                              ;ignore
 (bar x))

Only the first and fourth method is supported by CommonLisp though
there is no guarantee that the fourth method will not produce
redundant code. Because of that the fourth method is undesirable.
>From what I can tell, the L/G-machine compiler will not produce
redundant code but I haven't checked for Ivory. Does Symbolics
guarantee that method four will never generate redundant code
on any of their machines? Also, I don't know whether Lucid or
Franz will generate redundant code for method four. Can anybody
enlighten me on this question?

>From what I can tell, neither Lucid nor Franz support the second
method. Lucid supports the third method but Franz does not.
The Symbolics L/G-machine compiler will not produce redundant code
for the third method. I haven't checked the Ivory for this example.

What's the point of this all? There are two problems with all of

First of all I want to write something like:

(loop for x in l collect t)

This is a simple way of creating a list of t's which is the same
length as l. I know there are other ways but I think that this
way generates the most efficient code. The problem is that the
lexical variable x is never accessed and the compiler will give
me a warning. (Actually, the L/G-machine compiler doesn't for some
reason but Ivory does. I think the Ivory compiler is correct on
this one.) I can't use the first method discussed above because
there is no way specified in CommonLisp (at least that I know
of) for putting a declaration inside a loop. I can't use the
second or third method because it is not supported by CommonLisp.
I could use the fourth method:

(loop for x in l
      do x                                      ;ignore
      collect t)

except for two problems. First, there is no guarantee that other
compilers will not generate redundant code for this. Second, while
this works for the L/G-machine compiler, the Ivory compiler still
issues a warning that x is never accessed. Presumably, Ivory is
optimizing away the ``do x'' and then issuing the warning. (Actually
there are two potential sources of redundancy here. There is the
code for ``do x'' and then there is the code for binding x due
to ``for x in l'' which is separate from the code which cdrs down l.)
Likewise, for method four there is no guarantee that other compilers
won't also issue warnings for this case. So none of the methods
are applicable for this example. What do I do?

The second problem is that often I write macros to set up lexical
environments for forms. For example:

(defmacro WITH-MY-LEXICAL-VARIABLES (&body body)
  `(let ((x (foo))
         (y (bar)))

(defun BAZ ()
  (+ (* x x) (* y y))))

(defun QUUX ()
  (* x x)))

As this example shows, I write a macro to set up the general lexical
environment that I need though each call doesn't necessarilly use
all of the lexical variables. I would like to prevent the compiler
from issuing warnings in this case. The problem is that if I use
the first method:

(defmacro WITH-MY-LEXICAL-VARIABLES (&body body)
  `(let ((x (foo))
         (y (bar)))
     (declare (ignore x y))

then the compiler will complain when I access the variables (and
rightfully so). The second method is inappropriate here. The third
method is not supported by CommonLisp. If I fake the third method
by writing an IGNORE function then I get redundant code. Finally,
the fourth method:

(defmacro WITH-MY-LEXICAL-VARIABLES (&body body)
  `(let ((x (foo))
         (y (bar)))
     x y

will work, but there is no guarantee that redundant code won't be
generated and a given compiler may optimize away the references to
x and y and still issue a warning. What do I do?