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

Issue: LET-TOP-LEVEL (version 1)



re:   (let ((x (big-computation-that-returns-22/7)))
        (defmacro foo (y) `(list ,x ,y))
        (defun bar (z) (foo (1+ z))))
    (bar 2) => (22/7 3) if it evaluates to anything, but how could the
    compiler know that?

This is perhaps a bad example of what you are trying to illustrate, for it
needlesly violates the "global environment" constraint of CLtL p145.

Since you are merely trying to show up a flaw in the "pre-processor" style
of evaluators (that pervasively expand macros before beginning evaluation),
you could adequately point that out with:

    (let ((x (big-computation-that-returns-22/7)))
      (defmacro foo (y) `(quote ,y))
      ;; or, use variant:  (eval '(defmacro foo (y) `(quote ,y)))
      (print x)
      (defun bar (z) (foo (1+ z))))

[The problem is that the "call" to FOO inside BAR is resolved and macro-
expanded during the pre-process phase, at which time the "wrong" decision
will be made regarding it;  during the evaluation phase, FOO will have
the macro definition of `(quote ,y) installed, but that is too late].

This also illustrates a problem with current compilation techniques (or,
rather,  with the current lack of a definition for "top-level"), but without
involving the macro-expansion function in a lexical-capturing situation.

On the other hand, if we relenquish the strictures of CLtL p145 (which
some implementations do), then I don't see any problem with the following 
example:

;;; Beginning of file

    (eval-when (eval compile)
       (let ((cnt 0))
	 (defmacro do-it-once (x) (incf cnt) `(PRINT ,x))
	 (defmacro total-count () ',cnt))
    )

    (defun foo (x)
      (do-it-once x) 
      (do-it-once x)
      (total-count))

;;; End of file


So I'm wondering what is meant by the claim:

  "When you define a macro with a non-null closed-over environment, it is 
   clear that the compiler cannot know how to evaluate the expansion function.
   It is therefore reasonable to assume that the compiler cannot expand uses 
   of that macro during the same compilation that encounters the DEFMACRO form.
   If you want a macro like this, you must put the DEFMACRO in a separate file,
   compile and load that file, and then compile any uses of the macro."

If this claim was intended to be limited to "solitary forms", as opposed
to files, then the following pathelogical function should be considered:

(defun tryit () 
  (compiler-let ((cnt 0))
    (compiler-let ((throw-away
		     (progn 
		       (defmacro do-it-once (x) (incf cnt) `(QUOTE ,x))
		       (defmacro total-count () `(QUOTE ,cnt))
		       t)))
      (defun foo (x)
	(do-it-once x) 
	(do-it-once x)
	(total-count)))))

I can make some sense of this claim if I make a lot of presumptions about
the notion of "top-level";  but this is still a murky area ("top-level").
For example, if the notion of top level "passes through"  LET as well as
through COMPILER-LET, then the claim makes enough sense to be discussed;
and in that discussion, I would offer rebutting cases similar to the
ones above.


-- JonL --