From: Peter Seibel
Subject: Predicate for defconstant "different"
Date: 
Message-ID: <m3znnhdu1o.fsf@localhost.localdomain>
In the DEFCONSTANT dictionary entry it says:

  A constant defined by defconstant can be redefined with defconstant.
  However, the consequences are undefined if an attempt is made to
  assign a value to the symbol using another operator, or to assign it
  to a different value using a subsequent defconstant.

Following "different" to the glossary and then onto "same" I see this:

  2. (of objects if no predicate is implied by context)
  indistinguishable by eql.

Am I correct in interpreting the verbiage at DEFCONSTANT as not
implying a predicate, therefore DEFCONSTANT can only be used to
redefine a constant to a "same-under-eql" value?

A perhaps related question:

If I want to create a package into which I'm going to stash a bunch of
symbols created at runtime, can I use a constant to hold the package?
For example something like:

  (defconstant +foo-package+ #.(or (find-package "FOO") (make-package "FOO")))

Or is that (a) broken or (b) bad form?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra

From: Kent M Pitman
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <sfwznnh57uo.fsf@shell01.TheWorld.com>
Peter Seibel <·····@javamonkey.com> writes:

> In the DEFCONSTANT dictionary entry it says:
> 
>   A constant defined by defconstant can be redefined with defconstant.
>   However, the consequences are undefined if an attempt is made to
>   assign a value to the symbol using another operator, or to assign it
>   to a different value using a subsequent defconstant.
> 
> Following "different" to the glossary and then onto "same" I see this:
> 
>   2. (of objects if no predicate is implied by context)
>   indistinguishable by eql.
> 
> Am I correct in interpreting the verbiage at DEFCONSTANT as not
> implying a predicate, therefore DEFCONSTANT can only be used to
> redefine a constant to a "same-under-eql" value?

Yes and No.

You are correct that the verbiage in DEFCONSTANT implies EQL.

You are incorrect about the consequent "can only be used" part.
You _can_ do (defconstant +magic+ 1) and later change it to 
(defconstant +magic+ 2).  What the passage is telling you is that if you
do, the system is not responsible for finding all places that have made
assumptions.  If you have some function (defun foo (x) (+ x +magic+))
that you do not then redefine, it might or might not see the new value
of +magic+.  Your responsibility is to assure that if it needs to see the
new value, it gets redefined at the same time as you make the change to
the constant's definition.
 
> A perhaps related question:
> 
> If I want to create a package into which I'm going to stash a bunch of
> symbols created at runtime, can I use a constant to hold the package?
> For example something like:
> 
>   (defconstant +foo-package+ #.(or (find-package "FOO") (make-package "FOO")))
> 
> Or is that (a) broken or (b) bad form?

Since DELETE-PACKAGE can occur, and since therefore +foo-package+ can end
up with a new package name, you can get inconsistent values of +foo-package+.

But this isn't the real reason not to use defconstant here.  The REAL reason
dosen't have to do with redefinability of the constant, but rather the fact
that DELETE-PACKAGE doesn't run any hook function that will notice that your
code has been broken and needs to be recompiled.

I recommend just using a special variable, so that if someone does 
DELETE-PACKAGE,  they can learn to also reset the variable to a new package.
The nice thing about a special variable is that its clients will all pick
up the new value automatically without recompilation.
From: james anderson
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <3E82F8B9.FEF0F183@setf.de>
Kent M Pitman wrote:
> 
> Peter Seibel <·····@javamonkey.com> writes:
> 
> > ...
> > Am I correct in interpreting the verbiage at DEFCONSTANT as not
> > implying a predicate, therefore DEFCONSTANT can only be used to
> > redefine a constant to a "same-under-eql" value?
> 
> Yes and No.
> 
> You are correct that the verbiage in DEFCONSTANT implies EQL.
> 
> You are incorrect about the consequent "can only be used" part.
> You _can_ do (defconstant +magic+ 1) and later change it to
> (defconstant +magic+ 2).  What the passage is telling you is that if you
> do, the system is not responsible for finding all places that have made
> assumptions.

i had come to the conclusion that, where the spec says "However, the
consequences are undefined if an attempt is made ... to assign a different
value using a subsequent defconstant," the effective implication is that one
cannot do this. as in

? (defconstant *x* 1)
*X*
? (defConstant *x* 2)
> Error: Constant *X* is already defined with a different value
> While executing: CCL::DEFINE-CONSTANT
> Type Command-/ to continue, Command-. to abort.
> If continued: Redefine *X* anyway
See the Restarts� menu item for further choices.
1 > 
*X*
? 

which, while continuable, effective precludes it in practice. do i understand
correctly from the rather emphatic "_can_" above, that such a consequence is
arguably non-conformant?

...
From: Kent M Pitman
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <sfwel4tszyy.fsf@shell01.TheWorld.com>
james anderson <··············@setf.de> writes:

> Kent M Pitman wrote:
> > 
> > Peter Seibel <·····@javamonkey.com> writes:
> > 
> > > ...
> > > Am I correct in interpreting the verbiage at DEFCONSTANT as not
> > > implying a predicate, therefore DEFCONSTANT can only be used to
> > > redefine a constant to a "same-under-eql" value?
> > 
> > Yes and No.
> > 
> > You are correct that the verbiage in DEFCONSTANT implies EQL.
> > 
> > You are incorrect about the consequent "can only be used" part.
> > You _can_ do (defconstant +magic+ 1) and later change it to
> > (defconstant +magic+ 2).  What the passage is telling you is that if you
> > do, the system is not responsible for finding all places that have made
> > assumptions.
> 
> i had come to the conclusion that, where the spec says "However, the
> consequences are undefined if an attempt is made ... to assign a different
> value using a subsequent defconstant," the effective implication is that one
> cannot do this. as in
> 
> ? (defconstant *x* 1)
> *X*
> ? (defConstant *x* 2)
> > Error: Constant *X* is already defined with a different value

Yes, a strict reading of the spec does lead you to think this, but there
is really no good reason for an implementation not to make this a 
continuable error, and I believe all implementations do.  When they allow
you to proceed, what they are saying is what I said before--that you're
on your own for causing all necessary redefinitions to happen.

A Common Lisp program itself then, might not be conforming if it does
such a redefinition dynamically at runtime.  But if an implementation
permits this, it's usually assuming that you are not writing a program
that changes the definition, but instead changing a program that does
not change the definition.  And that's just an "environment issue" of
how easy the implementation makes it to undo your programming errors
while developing.

> > While executing: CCL::DEFINE-CONSTANT
> > Type Command-/ to continue, Command-. to abort.
> > If continued: Redefine *X* anyway

This indicates it to be a continuable error.

> See the Restarts� menu item for further choices.
> 1 > 
> *X*
> ? 
> 
> which, while continuable, effective precludes it in practice.

No, it precludes it at runtime.  If you are PLANNING to change the value,
you should be using defvar or defparameter, which have the semantics that
says "get the value fresh every time since it might change".

> do i understand
> correctly from the rather emphatic "_can_" above, that such a consequence is
> arguably non-conformant?

Only if you think of the change as part of one big program.  If you think
of the change as occurring at the meta-level, when what I was saying was
that the spec does not preclude an implementation from letting you continue
to work in the same image.
From: Duane Rettig
Subject: Continuable error as "Really Important Warning" (was: Predicate for defconstant "different")
Date: 
Message-ID: <48yv0914y.fsf_-_@beta.franz.com>
james anderson <··············@setf.de> writes:

> i had come to the conclusion that, where the spec says "However, the
> consequences are undefined if an attempt is made ... to assign a different
> value using a subsequent defconstant," the effective implication is that one
> cannot do this.

This is an incorrect assumption.  To provide one implementor's point
of view, let me take you through my logic.

Anytime there is a potential tripping point for a user, it is likely
that we wil create a condition out of that situation.  What kind of
condition will depend on the severity of the situation, and on the
liklihood that ignoring the issue will cause the user problems.

Our own hierarchy of conditions is shown in

http://www.franz.com/support/documentation/6.2/doc/errors.htm#errors-intro-1

Now, there are several levels of action that can be required.

- The simplest for the implementor and the potentially hardest for
the user is to not signal any condition for the situation. This is
sometimes consciously done by us or allowed by the user to preserve
speed, but is discouraged in safe situations.

- The next easiest is the error; we can't allow this particular
situation, because if we did, the user would be hosed.  A
non-continuable error disallows a return, but, unlike other
languages, it doesn't disallow working around the error programmatically;
invoking restarts provides a lot of power to the user to back up
a little bit and re-try from a point "before" the erroneous situation
showed up.  Most Lisp debuggers allow stack frames to be traversed and
visited, and to restart frames (presumably from such a point before there
was an erroneuos situation, and hopefully after correcting the cause
of the situation).

The implications for the implementor (whether it is the Lisp vendor or
a programmer who places a call to ERROR) is that is is guaranteed that
the error will never return, so the code after the error call but before
the next rerunnable point (e.g. restart, catch, unwind-protect cleanup)
will not have to deal with the lisp being in that error situation.

- The next category to peel of is informational notation.  We have a
condition called compiler-note, for example, which the user normally
does not see unless the compilation is done with non-nil combinations
of *compile-print* and *compile-verbose*.  This allows information that
is not likely to affect the operation of the compiled code to be given,
in case the user wants to see it.

- The last two major categories of notification are warning and
continuable error.  Note that continuable error is not hierarchical,
but a dimension established by the way the condition is signalled
(i.e. by calling CERROR):

 1. The danger in issuing a warning is that it is never known how
many such warnings the user is looking at, and thus it is not known
whether the user will actually _see_ the warning.  We have in fact
had users who became angry at us for calling WARN, but since the
user didn't see it in the reams of other warnings that were being
issued, the important one was missed and there was a loss of work
trying to find the problem.

 2. The danger of calling CERROR is that it _requires_ explicit
intervention by the user.  If the condition is expected, then the
intervention need not be interactive, since like error the programmer
can programmatically continue and/or select restarts.

The good things about warnings and restarts are that each provide
a level of control that is fine-grained, well-known, and portable.
A warning allows information to be shoved toward the user without
impeding the progress of whatever is happening.  A continuable
error allows the programmer to unconditionally grab the attention
of the user and effectively say "you _must_ do something with this!"

This whole system of reporting and levels of demand for intervention
is a huge step up from most other languages which have a simple
warning/fatal-error dichotomy, or which have numeric return codes
signifying degree of severity (like the 0 = success, 4 = warning,
etc, return codes of JCL and Fortran ilk).

I'm sure I've left out some aspects of this, but my goal was to
provide a relatively complete but simplistic high-level view of
it from my own viewpoint.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Peter Seibel
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <m3he9oectz.fsf@localhost.localdomain>
Kent M Pitman <······@world.std.com> writes:

> You are incorrect about the consequent "can only be used" part. You
> _can_ do (defconstant +magic+ 1) and later change it to (defconstant
> +magic+ 2). What the passage is telling you is that if you do, the
> system is not responsible for finding all places that have made
> assumptions. If you have some function (defun foo (x) (+ x +magic+))
> that you do not then redefine, it might or might not see the new
> value of +magic+. Your responsibility is to assure that if it needs
> to see the new value, it gets redefined at the same time as you make
> the change to the constant's definition.

Okay, that helped a lot. Here's my current understanding (really just
a restatement, I think, of what you said) of the practical reality of
constants defined with DEFCONSTANT. I'd be happy to have the bugs in
my understanding pointed out:

References to constants defined with DEFCONSTANT will (can?) be
interpreted/compiled with the current value of the constant inlined.
So if you redefine a constant, any definitions that refer to the
constant that have *already* been evaluated are likely to continue
using the old value while definitions evaluated after the redefinition
will see (and inline) the new value, leading to an inconsistent image,
if you don't go back and reinterpret/recompile the definitions that
currently are using the old value.

During development, that inconsistency may be acceptable so
implementations may support redefining constants rather than forcing
you to start a new image. (In theory, a really snazzy implementation
could keep track of which definitions referenced the constant and
therefore need to be reevaluated. It could even, assuming it kept
enough information with it's compiled code, patch them, with or
without asking you, as *all* the consequences are undefined. Out of
curiosity, is there a reason this is "undefined" rather than
"implementation defined"?)

The other consequence of using DEFCONSTANT is that the name will
answer T to CONSTANTP. Which means clever macros could inline the
value at macro expansion time. For instance, a macro could use a code
walker to find all the symbols used as non-local variable references
and replace them with the result of passing the symbol to a function
like:

  (defun possibly-constant-value (symbol)
     (if (constantp symbol) (symbol-value symbol) symbol)


Is all that correct? Sorry I'm being so dense about this--I feel like
I'm close though.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Kent M Pitman
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <sfw65q45w85.fsf@shell01.TheWorld.com>
Peter Seibel <·····@javamonkey.com> writes:

[...]
> During development, that inconsistency may be acceptable so
> implementations may support redefining constants rather than forcing
> you to start a new image. (In theory, a really snazzy implementation
> could keep track of which definitions referenced the constant and
> therefore need to be reevaluated.

Yes, though this gets into complex questions of whether it should
cache the original definition (the one logically associated with the
old value in a set of consistent sources, which might have been
superseded textually since that time) or whether it should use the new
definition (one that might or might be logically associated with the
new value, depending on whether the new value was due to a change in
the source or merely due to a repeated call to a non-reproducible
function [as in (defconstant randomness (random 1000)) or (defconstant
mycompiletime (get-universal-time))].  In the case that the change
requiring the update is textual, requiring new code, you have other
problems like whether the macros supporting the new definition are
textually consistent and already loaded in order to support the
re-evaluation.  In the other case, you have the problem that your
super-smart system is using two incompatible sets of sources to
dynamically cobble together a working version.  It's really unlikely
any system is going to get this right 100% of the time, since there is
not a 100% consistent rule of what _is_ right that stops short of
meta-modeling the entire system and all of your changes dynamically,
which requires something that is _outside_ of DEFCONSTANT (grasping
the entire development environment) not something _inside_ of
DEFCONSTANT (just doing some small bit of backward chaining, as it
might appear at first glance).  So what you say is right in a naive
kind of way--just don't expect it to really ever happen like you're
thinking for reasons that are pretty subtle.

Back in the now-long-distant future, when lisp machines roamed the land 
and all lisp programmers made a decent wage and were actively happy
with what they did, we routinely tried experiments like this that
seemed obvious, and we went with as many of them as we could.  
We had long design discussions about making source code be database-based
instead of file-based so that dependencies could be kept narrow and you
didn't have to do lots of useless updating, too.  It was great fun and
the then-future seemed so bright.  It all seems so much farther away
now, and not for any good reason, other than that we haven't the surplus
cash to care about the future any more, at least in part because some
of us think that it's a bad idea for people to make too much money
from software.

> It could even, assuming it kept
> enough information with it's compiled code, patch them, with or
> without asking you, as *all* the consequences are undefined. Out of
> curiosity, is there a reason this is "undefined" rather than
> "implementation defined"?)

There is a technical requirement for conformance that requires
implementations to document every "implementation-defined" behavior,
but no such requirement for undefined.  I think we tried to be
conservative about how often to force that expense of requiring such
documentation.  Maybe we worried that documenting the precise behavior
could be tricky in some implementations?  But then again, there was also
a cost to us to consider whether to make something undefined or
implementation-defined, in that we had to waste meeting time on it.  And
someone had to prepare an agenda. And so on.  We did some of this stuff
in big block votes, which is how at least some of the argument type 
checking stuff got in--I did a lot of error terminology by handwaving
and rushed votes because people seemed to want me to.  Often that
resulted in little surprises later (hopefuly mostly good ones, offsetting
a few troublesome ones).  But it's no substitute for careful design.
All in all, I'd say you're asking about an area of the standard
(undefined vs implementation-defined) that is at the fringe of what we 
spent conscious energy on, and sometimes there was no actual thought
given at all.

> The other consequence of using DEFCONSTANT is that the name will
> answer T to CONSTANTP. Which means clever macros could inline the
> value at macro expansion time. For instance, a macro could use a code
> walker

[already tough to write portably, but ok...]

> to find all the symbols used as non-local variable references
> and replace them with the result of passing the symbol to a function
> like:
> 
>   (defun possibly-constant-value (symbol)
>      (if (constantp symbol) (symbol-value symbol) symbol)
> 

The compiler is likely to already do this.  I'm not sure there is a point
to asking a less-well-informed tool like a user-macro to do it, too.
If the compiler doesn't do this, it's probably for good reason.  I'd
send a bug report, not reinvent the wheel.

> Is all that correct? Sorry I'm being so dense about this--I feel like
> I'm close though.

Sort of, I think, modulo the advisability of actually doing it.
Most of what you said is conceptually right, just also mostly not 
advisable for the reasons I've cited. ;)  So if you're just sanity
checking your understanding, you're probably ok.  If you're proposing
future work, that's another matter.  Heh.
From: Peter Seibel
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <m3d6kce1bq.fsf@localhost.localdomain>
Kent M Pitman <······@world.std.com> writes:

> Peter Seibel <·····@javamonkey.com> writes:
> 
> > For instance, a macro could use a code walker
> 
> [already tough to write portably, but ok...]

Well, I didn't show it for a reason. ;-)

> > to find all the symbols used as non-local variable references and
> > replace them with the result of passing the symbol to a function
> > like:
> > 
> >   (defun possibly-constant-value (symbol)
> >      (if (constantp symbol) (symbol-value symbol) symbol)
> > 
> 
> The compiler is likely to already do this. I'm not sure there is a
> point to asking a less-well-informed tool like a user-macro to do
> it, too. If the compiler doesn't do this, it's probably for good
> reason. I'd send a bug report, not reinvent the wheel.

Okay, so the what the heck is CONSTANTP for?

> > Is all that correct? Sorry I'm being so dense about this--I feel
> > like I'm close though.
> 
> Sort of, I think, modulo the advisability of actually doing it. Most
> of what you said is conceptually right, just also mostly not
> advisable for the reasons I've cited. ;) So if you're just sanity
> checking your understanding, you're probably ok. 

That's the goal. Thanks a lot.

> If you're proposing future work, that's another matter. Heh.

Nah. Not yet. ;-) Though a database backed source code repository,
especially one with transactions (e.g. defun, defun, defun, commit.)
would be pretty snazzy. But not on the top of my todo list.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Kent M Pitman
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <sfwznngp80d.fsf@shell01.TheWorld.com>
Peter Seibel <·····@javamonkey.com> writes:

> > >   (defun possibly-constant-value (symbol)
> > >      (if (constantp symbol) (symbol-value symbol) symbol)
> > > 
> > 
> > The compiler is likely to already do this. I'm not sure there is a
> > point to asking a less-well-informed tool like a user-macro to do
> > it, too. If the compiler doesn't do this, it's probably for good
> > reason. I'd send a bug report, not reinvent the wheel.
> 
> Okay, so the what the heck is CONSTANTP for?

[Not that it has to be _for_ anything, of course...  Some operators
 we just put in there to see if you're awake... Just kidding...
 Probably.]

I was objecting to your use of a code-walker, not to your use of
constantp within it, which was sort of weirdly right even though
misplaced.

You might use this for your own functions when writing compiler macros,
for example.  Compiler macros allow you to access the natural code-walking
of the compiler at the appropropriate hook point that allows you to make
a local transformation without trying to worry about how the traversal
goes.

 (defun vector-length (x)
   (length (the vector x)))

 (define-compiler-macro vector-length (&whole form vector-form)
   (if (constantp vector-form)
       (let ((vector (eval vector-form)))
         (check-type vector vector)
         (length (the vector vector)))
       form))
From: Pekka P. Pirinen
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <uwuifo02z.fsf@globalgraphics.com>
Kent M Pitman <······@world.std.com> writes:
> Peter Seibel <·····@javamonkey.com> writes:
> > Okay, so the what the heck is CONSTANTP for?
>
> [...]
> You might use this for your own functions when writing compiler macros,
> for example.  [...]
> 
>  (defun vector-length (x)
>    (length (the vector x)))
> 
>  (define-compiler-macro vector-length (&whole form vector-form)
>    (if (constantp vector-form)
>        (let ((vector (eval vector-form)))
>          (check-type vector vector)
>          (length (the vector vector)))
>        form))

Yes, but, any time you write transformations that use the semantics of
code, you should take care to do it in the right environment, so:

  (define-compiler-macro vector-length (&whole form vector-form
                                        &environment env)
    (if (constantp vector-form env)
        (let ((vector (eval vector-form env))) ; not CL!
          (check-type vector vector)
          (length (the vector vector)))
        form))

Except there is no environment argument to EVAL, and ENCLOSE didn't
make it into the standard, so it's tricky to write portable compiler
macros that use CONSTANTP, because there is no portable way to access
the value of the constant in the compilation environment (as defined
in ANS 3.2.1).

You can make sure your constant definitions are in the evaluation
environment, by loading them from another file, or wrapping them in
EVAL-WHEN.  If you EVAL arbitrary forms, like above, you need to be
careful about macros and inline functions as well.
-- 
Pekka P. Pirinen
 To have mercy in your heart, you must feel for the guilty;
 the innocent have no need of it.
From: Gabe Garza
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <87he9o5j4i.fsf@ix.netcom.com>
Peter Seibel <·····@javamonkey.com> writes:

> Okay, so the what the heck is CONSTANTP for?
> 

(defun my-expensive-function (argument)
  (sleep 5)
  (sqrt argument))                

(define-compiler-macro my-expensive-function (&whole form argument)
  (if (constantp argument)
    `',(my-expensive-function (eval argument))
    form))


CL-USER 3 > (time (my-expensive-function 3))
Elapsed time =   0:00:05
1.7320508075688772

CL-USER 4 > (time (defun foo () (my-expensive-function 3)))
Elapsed time =   0:00:00
FOO

CL-USER 5 > (time (compile 'foo))
Elapsed time =   0:00:05
FOO

CL-USER 6 > (time (foo))
Elapsed time =   0:00:00
1.7320508075688772

CL-USER 7 > (defconstant +constant+ 4)
+CONSTANT+

CL-USER 8 > (time (my-expensive-function +constant+))
Elapsed time =   0:00:05
2.0

CL-USER 9 > (time (defun bar () (my-expensive-function +constant+)))
Elapsed time =   0:00:00
BAR

CL-USER 10 > (time (compile 'bar))
Elapsed time =   0:00:05
BAR

CL-USER 11 > (time (bar))
Elapsed time =   0:00:00
2.0

CL-USER 12 > (time (defun baz (arg) (my-expensive-function arg)))
Elapsed time =   0:00:00
BAZ

CL-USER 13 > (time (compile 'baz))
Elapsed time =   0:00:00
BAZ

CL-USER 14 > (time (baz 4))
Elapsed time =   0:00:05
2.0

I really wish more of the environment functions had "made it in".

Gabe Garza
From: Barry Margolin
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <dWJga.4$2a1.1109@paloalto-snr1.gtei.net>
In article <··············@localhost.localdomain>,
Peter Seibel  <·····@javamonkey.com> wrote:
>Okay, that helped a lot. Here's my current understanding (really just
>a restatement, I think, of what you said) of the practical reality of
>constants defined with DEFCONSTANT. I'd be happy to have the bugs in
>my understanding pointed out:
>
>References to constants defined with DEFCONSTANT will (can?) be
>interpreted/compiled with the current value of the constant inlined.
>So if you redefine a constant, any definitions that refer to the
>constant that have *already* been evaluated are likely to continue
>using the old value while definitions evaluated after the redefinition
>will see (and inline) the new value, leading to an inconsistent image,
>if you don't go back and reinterpret/recompile the definitions that
>currently are using the old value.

This sounds right.  In most implementations, I'd expect inlining to be done
by the compiler, but not the interpreter.  But some implementations
(e.g. CMUCL) use the compiler to implement most of the interpreter, so
they may inline in both circumstances.

>During development, that inconsistency may be acceptable so
>implementations may support redefining constants rather than forcing
>you to start a new image. (In theory, a really snazzy implementation
>could keep track of which definitions referenced the constant and
>therefore need to be reevaluated. It could even, assuming it kept
>enough information with it's compiled code, patch them, with or
>without asking you, as *all* the consequences are undefined. Out of
>curiosity, is there a reason this is "undefined" rather than
>"implementation defined"?)

If it were implementation-defined, programmers might be tempted to depend
on the implementation's behavior in production code (perhaps protected by
appropriate #+ checks), and we didn't want to encourage this type of
programming.

>The other consequence of using DEFCONSTANT is that the name will
>answer T to CONSTANTP. Which means clever macros could inline the
>value at macro expansion time. For instance, a macro could use a code
>walker to find all the symbols used as non-local variable references
>and replace them with the result of passing the symbol to a function
>like:
>
>  (defun possibly-constant-value (symbol)
>     (if (constantp symbol) (symbol-value symbol) symbol)
>
>
>Is all that correct? Sorry I'm being so dense about this--I feel like
>I'm close though.

Yes, that's correct.

-- 
Barry Margolin, ··············@level3.com
Genuity Managed Services, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Steven M. Haflich
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <3E871612.2060604@alum.mit.edu>
Peter Seibel wrote:
> 
> If I want to create a package into which I'm going to stash a bunch of
> symbols created at runtime, can I use a constant to hold the package?
> For example something like:
> 
>   (defconstant +foo-package+ #.(or (find-package "FOO") (make-package "FOO")))
> 
> Or is that (a) broken or (b) bad form?

(BTW, I consider almost any use of read-time-eval to be bad style.)

Your original question has devolved into discussion about the semantics
of defconstant.  These are interesting questions, but they don't address
how you should best accomplish your original intention.

Often the purpose of defining a constant is twofold: To declare that the
value of the "constant" variable will thereafter be eql to the declared
value, and therefore, to permit the compiler to compile this value into
compiled functions as a constant.

If the constant value is _not_ compiled into the function as a manifest
constant, the constant value can still be obtained at execution time by
variable dereference.  But dereference may be slightly less efficient
than grabbing a manifest constant.

Special variables ae evil, like swear words in the language.  Constant
variables are only slightly less evil, and much use constant variables
can be accomplished with healthy, elegant, functional notation.

(defmacro package-constant (name)
   `(load-time-value (find-package ',name)))

Now, the above is more likely to be efficient across different
implementions than a deconstant (whether or not the defconstant is
portably legal).  It only works, of course, if the package is
already created at load time, but the usual practice is to build
systems in ways that this is true.
From: Kent M Pitman
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <sfwwuig35hm.fsf@shell01.TheWorld.com>
"Steven M. Haflich" <·················@alum.mit.edu> writes:

> (BTW, I consider almost any use of read-time-eval to be bad style.)

Mostly I agree with this.  Though I use them sometimes anyway.
Just as I mostly think using lists instead of defstructs for 
datastructures is not really the best thing.. but sometimes the
cost of doing 'the right thing' has to be weighed against the tiny
harm of doing 'the wrong thing' ...

> Special variables ae evil, like swear words in the language.

I definitely disagree with this.

Some things in the world are inherently dynamic.  I think it's
important to pick linguistic modeling techniques that map onto the
language neatly where a representation in the language is naturally
avialable.  If you're trying to model dynamic behavior, making a 
user-defined, impoverished substitute for specials isn't necessarily
going to be better.
From: Tim Bradshaw
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <ey31y0oaj4j.fsf@cley.com>
* Steven M Haflich wrote:

> Special variables ae evil, like swear words in the language.  Constant
> variables are only slightly less evil, and much use constant variables
> can be accomplished with healthy, elegant, functional notation.

What planet are you on? Special variables are one of the most powerful
features of Common Lisp.

--tim
From: Paolo Amoroso
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <G2iIPktAi0i29tv1u5D0brzWl68k@4ax.com>
On Sun, 30 Mar 2003 16:04:24 GMT, "Steven M. Haflich"
<·················@alum.mit.edu> wrote:

> (BTW, I consider almost any use of read-time-eval to be bad style.)

What are the few uses you think are appropriate?


Paolo
-- 
Paolo Amoroso <·······@mclink.it>
From: Nils Goesche
Subject: Re: Predicate for defconstant "different"
Date: 
Message-ID: <lyu1dizkkn.fsf@cartan.de>
Paolo Amoroso <·······@mclink.it> writes:

> On Sun, 30 Mar 2003 16:04:24 GMT, "Steven M. Haflich"
> <·················@alum.mit.edu> wrote:
> 
> > (BTW, I consider almost any use of read-time-eval to be bad
> > style.)
> 
> What are the few uses you think are appropriate?

How about this:

#.(setup-some-special-readtable)

<Some code with special syntax>

#.(restore-readtable)

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0