Subject: [clisp-list] Current CVS observations

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Wed Mar 26 05:52:08 2003

Christophe Rhodes wrote:

>And yet slightly more weirdness:
>Compiling the following:
>  (let ()
>    (eval-when (:compile-toplevel :load-toplevel :execute)
>      (defmacro foo () 'nil)))
>does not lead to a FOO macro being present after compilation.
>However, it doesn't lead to a FOO macro being present after loading
>the resulting .fas file, either.  Loading the source file works as
>expected.

My understanding of ANSI-CL eval-when is that your expectations are wrong.
Obviously, LET makes EVAL-WHEN not be at :*-toplevel. Thus everything happens as if NIL had been written instead of the whole eval-when form, at least in the compiler POV. No macro is seen.

I think this is a clear benefit of the renaming/clarification that happened between CLtL2 and ANSI-CL. :load/compile-toplevel is more expressive (and restrictive) than just the terms "compile load".

Another thing I once saw, but I'm not sure CLISP can be blamed on this. Expecting CLISP to sort out duplicate macro definitions for use by functions during compile-time of the same file is too much to be asked for:

(defmacro fast-position (elt sequence start end)
  `(position ,elt ,sequence :start ,start :end ,end))
#+clisp ; fast position on strings, added by Joerg Hoehle 2003
(when #+clisp (fboundp (find-symbol "VECTOR-POSITION" "EXT")) #-clisp nil
  (defmacro fast-position (elt sequence start end)
    `(ext::vector-position ,elt ,sequence ,start ,end)))
;(macroexpand-1 '(fast-position #\; "a;b" 0 3))
(defun foo (x) (fast-position #\newline x))

Both definitions occur at top-level. Which one shall the compiler remember for use during compilation in the same file? It cannot know.

So instead I wrote:
(defmacro fast-position (elt sequence start end)
  (if #+clisp (fboundp (find-symbol "VECTOR-POSITION" "EXT")) #-clisp nil
    `(ext::vector-position ,elt ,sequence ,start ,end)
    `(position ,elt ,sequence :start ,start :end ,end)))

Regards,
	Jorg Hohle.

---

From: Christophe Rhodes <[email-masked]>
Date: Wed Mar 26 06:24:31 2003

"Hoehle, Joerg-Cyril" <[email-masked]> writes:

> My understanding of ANSI-CL eval-when is that your expectations are
> wrong.  Obviously, LET makes EVAL-WHEN not be at :*-toplevel. Thus
> everything happens as if NIL had been written instead of the whole
> eval-when form, at least in the compiler POV. No macro is seen.

From the CLHS page for EVAL-WHEN

  The use of the situation :execute (or eval) controls whether
  evaluation occurs for other eval-when forms; that is, those that are
  not top level forms, or those in code processed by eval or
  compile. If the :execute situation is specified in such a form, then
  the body forms are processed as an implicit progn; otherwise, the
  eval-when form returns nil.

and a non-normative example:

  ;;;     The EVAL-WHEN in this case is not at toplevel, so only the :EXECUTE
  ;;;     keyword is considered. At compile time, this has no effect.
  ;;;     At load time (if the LET is at toplevel), or at execution time
  ;;;     (if the LET is embedded in some other form which does not execute
  ;;;     until later) this sets (SYMBOL-FUNCTION 'FOO1) to a function which
  ;;;     returns 1.
   (let ((x 1))
     (eval-when (:execute :load-toplevel :compile-toplevel)
       (setf (symbol-function 'foo1) #'(lambda () x))))

I quite agree that, at compile time, no side-effect should happen;
however, at load or execution time, there had better be a side effect:
note particularly the sentence "If the :execute situation ..."

> Both definitions occur at top-level. 

No they don't.  WHEN is not an operator that preserves top-levelness:
only LOCALLY, MACROLET, SYMBOL-MACROLET and PROGN do that.

Cheers,

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)