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

Function constants

I haven't followed the discussion on constants, so this might
repeat some material. 

The first question is what it means to be a function constant.  It
doesn't mean a constant function, which is a function that returns the
same thing every time it's called. But, does it mean that it has
an alterable environment?

(let ((a (list 1 2 3)))
  (labels ((f (x n) (+ x (nth n a)))
	   (g (x n) (setf (nth n a) x)))

Is G suitable as a function constant? How about F? I happen to think
both are suitable as function constants, and the intuitive behavior
should be enforced. The reason is that there is no structural
modification that is being done to the functions to alter them.
That it, there is nothing like

(setf (<some-part-of> F) <new-value>)

that is taking place, just the normal function invocation.

The second question is how do you dump such a thing as a function.
Well, if your compiler can compile-file this you are part way there:

(defun f (x y) (+ x y))

That is, you can dump and load functions.

The objection might be that a non-null environment is needed. If you
cannot compile-file this then you are out of conformance anyway:

(let ((a (list 1 2 3)))
  (defun (x n) (+ x (nth n a)))
  (defun g (x n) (setf (nth n a) x)))

So the remaining problem is how to dump ``code vectors.'' This is
simple if you have position-independent code, because then you just
dump the bits as if it were a bit-vector. The question is whether we
wish to support machines that have no such thing as position
independent code or do we wish to require implementations to keep
relocation information around (which they will anyway if they can
garbage collect code and compact the space). [Note that the
environments have to be put in something other than a readonly space,
one that the GC sees.]

There are possibly some other problems, such as the material that
might appear as additional information in something like a procedure
header. For example, links to other functions or weird system- or
machine-dependent information. I think we have to assume (and make it
absolutely clear) that we can only specify compilation when the
compiled code is being loaded into a Common Lisp that is identical to
the one doing the compiling (See the next paragraph.)

An alternative to the function constant problem is as follows: We
state that compilation is meaningful in only two situations: COMPILE
in an image with no dumping allowed and COMPILE-FILE in a fresh Lisp
where the compilation will not load any compiled code, where only one
compilation unit will be compiled, and where the result will be loaded
in a copy of the same fresh Lisp that was used to do the compilation.
Calls to COMPILE are allowed in the second scenario.  (That is, you
start a lisp, compile-file, quit, start afresh that same Lisp, load.)

In these two cases we can allow the free use of functions as constants
because either there is no need to dump stuff, or else all the source
code that is needed can be made available. That is, in this case, all
the functions that could be constants have either had their source
examined and saved by the very compiler doing all the work or else are
functions in the Common Lisp package, which can be dumped by name.

This case is a little restrictive, but this would be a conservative
case for which we are able to specify the meaning of compilation. Some
implementations might be able to handle less restrictive cases, but it
isn't required.