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

Re: Issue: EVAL-WHEN-NON-TOP-LEVEL (Version 5)



> Proposal (EVAL-WHEN-NON-TOP-LEVEL:GENERALIZE-EVAL):

I don't think this one is acceptable because it changes the conceptual
meaning of the EVAL and LOAD situations, even if it may not alter the
behavior in common usage.

> Proposal (EVAL-WHEN-NON-TOP-LEVEL:GENERALIZE-EVAL-NEW-KEYWORDS):
> 
>   As in GENERALIZE-EVAL, but rename the EVAL keyword to :EXECUTE,
>   the COMPILE keyword to :COMPILE-TOPLEVEL, and LOAD keyword to 
>   :LOAD-TOPLEVEL.
> 
>   Deprecate the use of keywords EVAL, COMPILE, and LOAD to EVAL-WHEN.
>   For compatibility, they are supported in EVAL-WHEN
>   at top-level, but their meaning is not defined elsewhere.

Now this has possibilities.  After all the discussion on this issue, I
am beginning to think that the only way to reach a good solution is to
junk the old situation names and define new ones so that we don't have
to worry about maintaining compatibility with existing rules that don't
make too much sense and aren't stuck with names that are more misleading
than mnemonic.

However, if we are willing to take that big a step, then I'm not sure
that this is the right set of situations.  In particular, I'm having
trouble imagining what the :LOAD-TOPLEVEL situation would be used for.
Here are the situations that I think would be useful:

  :EXECUTE  - execute at the normal time [as though there wasn't any
		EVAL-WHEN].
  :COMPILE-TOP-LEVEL - execute at compile time if at top level, with a
		preference for side-effects to be recorded in the
		compile-time environment instead of the resident
		environment.

	For example, this would be used to install the definition of a
	macro for use later in the file.

  :COMPILE-ALWAYS  - execute in a null lexical environment at compile
		time whether at top level or not.
		
	This would be less common, but could still be useful for things
	like noticing that a definition of a function exists in order to
	suppress warnings about calls to an undefined function.  That
	would be meaningful even if you didn't actually install the
	definition because it doesn't appear at top level.

  :COMPILE-PERMANENT - execute at compile time if at top level,
		side-effecting the resident environment.

	For example, you would want to use this for operations that
	create or alter a package.

The rationale probably should point out that all of this assumes that
distinctions between evaluated and compiled code are not portable, and
hence the standard doesn't need to specify how to do that.  An
additional reason for changing the situation names is so that
implementations could continue to use the EVAL and LOAD situations to
distinguish these for doing implementation-specific things.

Other comments:

>   ;; #4: This always does nothing. It simply returns NIL.
>  
>   (EVAL-WHEN (COMPILE)
>     (EVAL-WHEN (COMPILE) 
>       (PRINT 'FOO4)))

This case still bothers me.  Even if it is not something that would
commonly be done and the behavior is the consequence of otherwise
useful rules, this still seems completely counter-intuitive.

> Date: Sun, 12 Feb 89 16:40 EST
> From: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>
> Subject: Re: Issue: EVAL-WHEN-NON-TOP-LEVEL (Version 5)
...
> For example, it doesn't matter that
>   (EVAL-WHEN (COMPILE) (EVAL-WHEN (COMPILE) ...))
> doesn't execute anything. The reason is that you probably never really
> right this. Probably what really happens is Person 1 writes:
>   (DEFMACRO FOO () `(EVAL-WHEN (COMPILE) ...))
> and Person 2 writes:
>   (EVAL-WHEN (COMPILE) (FOO))
> Now all that's important is that Person 1 has asked himself the question
> "Should FOO do anything when in a non-top-level position?" If he has answered
> "Yes" to that, then he has made an extremely obvious programming error, and
> no complicated reasoning about nested EVAL-WHEN's is needed to notice it.
> If he has answered "No", then he presumably has a good reason. Then we have
> to ask, did the person implementing "FOO" document that the form was legitimate
> anywhere or only at top-level or what? If he documented that FOO was appropriate
> to use anywhere, and he still used only the COMPILE option, then he must have 
> somehow proven to himself that the contract of FOO could be satisfied without
> any work in some circumstances. Now the only remaining question is, did the
> user of FOO read and use that documentation properly. Since we've agreed that
> the doc says he could use it anywhere, then regardless of what 
>   (EVAL-WHEN (COMPILE) (EVAL-WHEN (COMPILE) ...))
> -does-, we know that it is doing what is intended.

I see two problems with this line of argument:  
(1) It is not obvious why the body of the outer (EVAL-WHEN (COMPILE)
...) should not be considered to be top level.
(2) The primary reason that person 1 used EVAL-WHEN was that they wanted
it to happen at compile time; considerations of top-level-ness is a
secondary detail.  Person 2 also wants it to happen at compile time.  So
this appears to be a case of two rights make a wrong.

> Date: Sun, 12 Feb 89 17:11:16 MST
> From: sandra%defun@cs.utah.edu (Sandra J Loosemore)
> Subject: Re: Issue: EVAL-WHEN-NON-TOP-LEVEL (Version 5)
> To:   Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>
> Cc:   sandra%defun@cs.utah.edu, CL-Compiler@SAIL.Stanford.EDU,
>       Moon@STONY-BROOK.SCRC.Symbolics.COM
> In-Reply-To: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>, Sun, 12 Feb 89 16:40 EST
> 
> I don't have any quibble with the behavior of the examples you cite.
> However, you still haven't said anything to justify the behavior of
> your proposal under example *I* cited in my previous message, namely,
> why
> 
>     (eval-when (load)
>         (defmacro foo ...))
> 
> should cause FOO to be defined in the compile-time environment even when
> the user explicitly specified that the macro only needs to be defined at
> load time.

I agree that this should do what is expected.

> Date: Mon, 13 Feb 89 13:39 EST
> From: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>
> Subject: Re: Issue: EVAL-WHEN-NON-TOP-LEVEL (Version 5)
> To:   sandra%defun@cs.utah.edu
> Cc:   KMP@STONY-BROOK.SCRC.Symbolics.COM, CL-Compiler@SAIL.Stanford.EDU,
>       Moon@STONY-BROOK.SCRC.Symbolics.COM
> In-Reply-To: <8902130011.AA02791@defun.utah.edu>
...
> Among other things, because it is incompatible with CLtL. p70 says:
> 
>  If the situation LOAD is specified
>  then if the situation COMPILE is also specified
>       then ...
>       else process each of the forms in the body in not-compile-time mode.
> 
> `not-compile-time' mode must see DEFMACRO because the previous page says that
> all top-level forms are defaultly processed in not-compile-time mode, which
> means that DEFMACRO is normally noticed by the compiler when in that mode.

Which is a reason for deprecating the "LOAD" situation and defining new
ones that can be defined better.

> Getting back to EVAL-WHEN, though, our semantics allow you to keep something
> from being `noticed' by the compiler by just putting it in a non-top-level
> position. 
>     (LET () (DEFMACRO FOO ...))
> is the easiest way to do that right now, but you can also write: 
>  (DEFUN INIT () 
>    (DEFMACRO ...)
>    (DEFMACRO ...) ...)
>  (INIT)

Sure, but controlling the time of execution is what EVAL-WHEN is
supposed to be for, so it seems odd that it works in some cases but not
others.

> Also, as a matter of pragmatics, I find that it is -extremely- rare to
> want DEFMACRO to not be seen at compile time but rather only to be seen at
> load time.

Agreed; the real problem is that EVAL-WHEN allows you to say things that
don't really mean what they appear to mean.