[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Date: Sun, 11 May 1986 21:06 EDT
From: Rob MacLachlan <RAM@C.CS.CMU.EDU>
Well, I freely admit that the big hole in my proposal is defining
what it means to "use" a VOID value. I think that the best approach
is to be extremely facist.
I've outlined reasonable design principles which suggest this is a bogus
thing do do. I hardly find your idea of ignoring those principles and
just arbitrarily pulling a semantics out of the air to be very convincing.
The only places where a void expression may be legal are:
1] Any place where the value is immediately discarded: PROGN, etc.
2] Any place in a function that can return multiple values. In
addition to tail-recursive positions, this includes the protected
form of UNWIND-PROTECT and the values form for
MULTIPLE-VALUE-PROG1 when these forms are in such a
I'm sorry, but I find this completely ridiculous. Many valid programs can be
written which use `void' values in ways other than this without being ill-formed.
Note that in either case, a void value may be illegal because the
result was declared to be of some other type:
(proclaim '(function frob-foo (foo) void))
(defun frob-foo (foo) ...)
(proclaim '(function make-foo ((member t nil)) foo))
(defun make-foo (frob-p)
(let ((foo (cons-a-foo)))
Suppose that FROB-FOO puts the FOO on the heap somewhere. Then suppose that
I have a function, CREATE-FOO, which is the only call of MAKE-FOO and is
(DEFUN CREATE-FOO (STASH-P)
(VALUES NIL NIL))
(VALUES (MAKE-FOO NIL) T))))
There's nothing ill-formed about the collection of programs which include
my program and yours.
In this classic "oops, I forgot to return the value" example, the
compiler is quite justified in giving a warning, since one branch of
the IF can never be legally executed. The function MAKE-FOO itself is
not erroneous, but the compiler could replace the call to FROB-FOO
with code that just signals an error. When this happens, I would like
my compiler to tell me that something may be wrong, since there almost
The programming problem you're worried about is a common one, but the technique
you're proposing for fixing it is just not practical. This situation comes up
in legitimate code (especially when macros are involved) all the time.
Consider the following common situation: I have a macro MYBLOCK which binds
the variable * to the value of the previous computation at the same level.
(DEFMACRO MYBLOCK (&BODY FORMS)
`(LET ((* *))
,@(MAPCAR #'(LAMBDA (FORM) `(SETQ * ,FORM)) FORMS)))
This lets me do:
(MYBLOCK 3 (+ * 5) (- * 2)) ==> 6
But what if the function FOO has a void return value? It's completely
reasonable to do:
(MYBLOCK (FOO) (BAR) (PRINT *))
because * gets assigned but never used.
The way the program can represent the information necessary to decide whether a
value is used correctly are endless. You really cannot mechanically detect them.