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

re: COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY



I have some concerns about the treatment of DEFCONSTANT in the proposal
COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY (I'm looking at version
6, June 9, 1988).  I realize that I have missed the previous discussion of
this topic, so I apologize if you have heard all of this before.

The assumption behind the proposal is that DEFCONSTANT should be as much
like DEFVAR and DEFPARAMETER as possible, but I think a more useful
model would be constant declarations in other languages.

Pascal has constant declarations that look like this:

  const MaxIndex = 100;
        MaxCount = 101;

Since there are often cases where the value of one constant depends on
another, many Pascal implementations extend this to permit the value to
be an expression that depends on previous constants:

  const MaxIndex = 100;
        MaxCount = MaxIndex+1;

This extension has been carried over into Modula and Ada.  
Now the obvious equivalent in Common Lisp would be 

  (defconstant max-index 100)
  (defconstant max-count (1+ max-index))

But, according to the proposal at hand, this is not really the same
because, while the first one declares a compile-time constant, the
second does not.  To get the desired effect, the proposal suggests
doing: 

  (defconstant max-index 100)
  (defconstant max-count #.(1+ max-index))

Besides being ugly, this won't work because there is nothing that
specifies that constants defined earlier in the file are made available
to the reader for use in evaluating #. expressions.  So maybe then the
answer is:

  (eval-when (eval compile load)
    (defconstant max-index 100)
    (defconstant max-count (1+ max-index)))

This will work, but seems unnecessarily verbose.  Note that both forms
need to be included in the EVAL-WHEN because otherwise there is no
guarantee that the first constant will be available to the compile-time
evaluation of the second.

It might be said that if you just write it the straight-forward way

  (defconstant max-index 100)
  (defconstant max-count (1+ max-index))

then a good compiler would be able to optimize this by recognizing that
the value expression in the second line involves only constants and go
ahead and fold it.  However, the proposal as written seems to
explicitly forbid this; it would be necessary to weasel around it by
saying that we can do the optimization so long as it is done in such a
way that the user can't tell the difference.  And this is not as easy as
it sounds.  Not only would you have to make sure that all variable names
referenced in the expression are DEFCONSTANTs, but they would have to be
defined earlier in the same file (else their value might change before
the current file is loaded), and their value must also have been folded.
All of this seems to me to lessen the usefulness of the DEFCONSTANT
feature.

I would prefer the standard to adopt the approach that we have taken on
the Explorer, namely that the value expression of a DEFCONSTANT is
always evaluated at compile time, and has access to other constants and
macros defined earlier in the file.  (However, because CLtL does not
specify this behavior, if there is an error during the evaluation, our
compiler just issues a warning message and causes evaluation to be
re-tried at load time.)