From: Vassil Nikolov
Subject: categories of constantness
Date: 
Message-ID: <7dem8t$hfc$1@nnrp1.dejanews.com>
This is a proposed classification of variables that we have or
might have in Common Lisp, including several types of
`constantness' of the variable.  The table below identifies
each category by the name of the defining form; the DEFINE-xxx
forms are not provided by ANSI Common Lisp and their names are
my own invention (perhaps they could be better).  The columns
that follow give relevant qualities that a variable possesses
or not depending on its category.

Depending on context, the notion of binding refers to either
lexical binding, dynamic binding, or any of the two.


category                   bindable assignable mutable eqlable
--------------------------------------------------------------
DEFCONSTANT                   no        no       no      no
DEFINE-CONSTANT-REFERENCE     no        no      yes     yes
DEFINE-STATIC-REFERENCE       no       yes      yes     yes
DEFVAR                       yes       yes      yes     yes

If X is the name of the defined entity,
`bindable'   means (LET (X) ...) is legal;
`assignable' means (SETQ X ...) is legal;
`mutable'    means (SETF (access-fn X) ...) is legal^1;
`eqlable'    means (EQL X X) => T^2.
____________________________________
^1 provided that the last value given to X was mutable
^2 across files: even if (DEFUN F () X) and (DEFUN G () X)
   occur in different files, (EQL (F) (G)) => T and that
   such equality is guaranteed


Notes:

There is demand for each of these categories.  In particular,
all but DEFVAR can be taken to guarantee access in O(1) time
in all `non-perverse' implementations (with deep binding,
accessing a (bindable) dynamic variable is in O(n)).

It is important that DEFCONSTANT provides precisely this
functionality (and not that of DEFINE-CONSTANT-REFERENCE)
since it cannot be defined by the user.  Specifically, the
user cannot declare that a constant variable's value may
be inlined (because it will not be compared by EQL), except
by using DEFCONSTANT in its present form.  On the other
hand, DEFINE-xxx-REFERENCE can be defined by the user even
now in ANSI Common Lisp (see the Appendix below).  Otherwise,
if the semantics of DEFINE-CONSTANT-REFERENCE is given to
DEFCONSTANT, then I propose that the INLINE declaration is
extended to cover also variables so that one could say

  (defconstant foo 'bar "baz")
  (declaim (inline foo))

to achieve the effect.  Or, with DEFCONSTANT as it is,
define (NOTINLINE DEFCONSTANT-CONSTANT) to make the
constant eqlable.

The issue of using LOAD-TIME-VALUE and MAKE-LOAD-FORM is
ignored.  I think I can afford not to let the worms out of
the can all at once, and I believe it is orthogonal to this
discussion as it pertains to how the value is prepared, not
how access to it via the variable is done.

DEFPARAMETER is the same as DEFVAR for the purposes of this
classification.

I propose that the name DEFGLOBAL be avoided since it is
unclear which category that name naturally denotes.

This classification is obviously not comprehensive, i.e.
it does not claim that there are no other useful yes/no
combinations.

There could be an analogy to C as follows (note how two
distinct Lisp categories map to the same C category):

  DEFCONSTANT               ---  const type const *
  DEFINE-CONSTANT-REFERENCE ---        type const *
  DEFINE-STATIC-REFERENCE   ---        type       *
  DEFVAR                    ---        type       *



Appendix---Defining DEFINE-xxx-REFERENCE

The idea is to have

  (define-static-reference foo 'init "doc")

expand into something like

  (progn
    (declaim (inline get-foo))
    (let ((foo-var 'init))
      (defun get-foo () foo-var)
      (defsetf get-foo (value) `(setq foo-var ,value)))
    (define-symbol-macro foo (get-foo))
    (setf (documentation 'foo 'variable) "doc"))

GET-FOO should be a gensym of course.  So should FOO-VAR to
avoid introducing gratuitous symbols into the package.
The implementation for DEFINE-CONSTANT-REFERENCE does not
have the DEFSETF form.

This has the property (I am not sure if it would be a bug)
that this global FOO may be shadowed by a local binding.
If this is undesirable, a candidate solution is to have

  (defconstant foo 'never-used "doc")

as the last form of the PROGN (at the same time doing
the job of the SETF of DOCUMENTATION).  Unfortunately
my reading of the spec doesn't say this is definitely
legal, only that it appears to be.

Another thing that is missing in the above outline is
taking care of repeated evaluation of the form.

[1999 Mar 26]

Vassil Nikolov <········@poboxes.com> www.poboxes.com/vnikolov
(You may want to cc your posting to me if I _have_ to see it.)
   LEGEMANVALEMFVTVTVM  (Ancient Roman programmers' adage.)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    

From: Kent M Pitman
Subject: Re: categories of constantness
Date: 
Message-ID: <sfwiubpj8p9.fsf@world.std.com>
Vassil Nikolov <········@poboxes.com> writes:

> This is a proposed classification of variables that we have or
> might have in Common Lisp [...]
> 
> category                   bindable assignable mutable eqlable
> --------------------------------------------------------------
> DEFCONSTANT                   no        no       no      no
> DEFINE-CONSTANT-REFERENCE     no        no      yes     yes
> DEFINE-STATIC-REFERENCE       no       yes      yes     yes
> DEFVAR                       yes       yes      yes     yes

It's worth noting that ISLISP has a defconstant that has the property
that you can bind it.  It was for this reason that DEFINE-SYMBOL-MACRO
was introduced into the language--so that code compatibility with that
other kind of DEFCONSTANT could be created by users instead of having
infinite variations provided by the system.  That's the reason I was
quick to suggest that DEFINE-SYMBOL-MACRO was a good solution--it was
put there just for that reason.

This remark isn't really intended as a reply to this table per se;
just a side note.
From: Pekka P. Pirinen
Subject: Re: categories of constantness
Date: 
Message-ID: <ixg16onjie.fsf@gaspode.cam.harlequin.co.uk>
Vassil Nikolov <········@poboxes.com> writes:
> It is important that DEFCONSTANT provides precisely this
> functionality (and not that of DEFINE-CONSTANT-REFERENCE)
> since it cannot be defined by the user.  Specifically, the
> user cannot declare that a constant variable's value may
> be inlined (because it will not be compared by EQL), except
> by using DEFCONSTANT in its present form.

But not being able to use EQL is not useful functionality, nor is
indiscriminate inlining of complex data structures.  As I point out in
an another thread, it easy to preserve EQLness by avoiding inlining
where this would break identity.  DEFCONSTANT should be defined to
preserve identity (and I'm rather astonished to hear that it
wouldn't).

>   (define-static-reference foo 'init "doc")
>
> expand into something like
>
>  (progn
>    (declaim (inline get-foo))
>    (let ((foo-var 'init))
>      (defun get-foo () foo-var)
>      (defsetf get-foo (value) `(setq foo-var ,value)))
>    ...

That won't work, because the FOO-VAR in the expansion of DEFSETF won't
refer to the local variable.  You want:

  (progn
    (declaim (inline get-foo (setf get-foo))
    (let ((foo-var 'init))
      (defun get-foo () foo-var)
      (defun (setf get-foo) (value) (setq foo-var value)))
    ...

Not many compilers will inline closures, though.
-- 
Pekka P. Pirinen    Harlequin Group plc, Cambridge, UK
A feature is a bug with seniority.  - David Aldred <david_aldred.demon.co.uk>
From: Vassil Nikolov
Subject: Re: categories of constantness
Date: 
Message-ID: <7dqbvj$7ei$1@nnrp1.dejanews.com>
In article <··············@gaspode.cam.harlequin.co.uk>,
  ·····@harlequin.co.uk (Pekka P. Pirinen) wrote:
> Vassil Nikolov <········@poboxes.com> writes:
> > It is important that DEFCONSTANT provides precisely this
> > functionality (and not that of DEFINE-CONSTANT-REFERENCE)
> > since it cannot be defined by the user.  Specifically, the
> > user cannot declare that a constant variable's value may
> > be inlined (because it will not be compared by EQL), except
> > by using DEFCONSTANT in its present form.
>
> But not being able to use EQL is not useful functionality, nor is
> indiscriminate inlining of complex data structures.  As I point out in

Why not?  Sometimes one does not need or want EQL but needs or wants
fastest possible operations on data.  In that case, inlining a constant
is useful functionality.  What is your objection?

There is a rough analogy between DEFCONSTANT and a C #define.  (As far
as I remember---haven't been there for a long time---the const qualifier
in C also permits inlining.)

> an another thread, it easy to preserve EQLness by avoiding inlining
> where this would break identity.  DEFCONSTANT should be defined to
> preserve identity (and I'm rather astonished to hear that it
> wouldn't).

Or maybe you want to be able to say, as I suggested, something like

  (defconstant foo 'init "doc")
  (declaim (notinline foo))

or, if you want the above to be the default, then I would insist to
be able to say something like

  (declaim (inline foo))
  (defconstant foo 'init "doc")

because I don't see how otherwise I could let the compiler inline
the constant (if it can) when I want speed most of all.

Note the phrase `something like': the syntax would need to be
refined to allow distinguishing between a constant variable FOO
and a function FOO.

As to your astonishment, the standard (as represented by the CLHS)
is pretty clear about the compiler being permitted (not required
of course) to inline constants, at least IMNSHO.

> >   (define-static-reference foo 'init "doc")
> >
> > expand into something like
> >
> >  (progn
> >    (declaim (inline get-foo))
> >    (let ((foo-var 'init))
> >      (defun get-foo () foo-var)
> >      (defsetf get-foo (value) `(setq foo-var ,value)))
> >    ...
>
> That won't work, because the FOO-VAR in the expansion of DEFSETF won't
> refer to the local variable.  You want:
>
>   (progn
>     (declaim (inline get-foo (setf get-foo))
>     (let ((foo-var 'init))
>       (defun get-foo () foo-var)
>       (defun (setf get-foo) (value) (setq foo-var value)))
>     ...

Yes, you are right.  I'll re-read the spec, of course, to see
exactly what I missed, but I see I confused the DEFSETF expander
(which should be defined in the appropriate lexical environment)
with the DEFSETF expansion.  My mistake.  Yet another reason why
it's a good thing to have (SETF FOO) as a function name.

> Not many compilers will inline closures, though.

Life is hard I guess...

I suppose it may be easier for implementors to provide
DEFINE-xxx-REFERENCE as a built-in, rather than to provide
the capability of inlining closures.

But my main point was that it is possible, albeit with some
loss of efficiency, for the users to define constant references
in Common Lisp themselves.

Vassil Nikolov <········@poboxes.com> www.poboxes.com/vnikolov
(You may want to cc your posting to me if I _have_ to see it.)
   LEGEMANVALEMFVTVTVM  (Ancient Roman programmers' adage.)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    
From: Fernando D. Mato Mira
Subject: Re: categories of constantness
Date: 
Message-ID: <3700CB81.80199CC0@iname.com>
Vassil Nikolov wrote:

> There is a rough analogy between DEFCONSTANT and a C #define.  (As far

If you look at things that way, then I prefer it to be called `DEFLITERAL'
as in ILOG Talk.
It also appears a bit better in my head regarding the EQL thing: ("Why can't
I compare something against a _constant_??
A `literal'? What's do you mean by `literal', precisely?").

--
Fernando D. Mato Mira
Real-Time SW Eng & Networking
Advanced Systems Engineering Division
CSEM
Jaquet-Droz 1                   email: matomira AT acm DOT org
CH-2007 Neuchatel                 tel:       +41 (32) 720-5157
Switzerland                       FAX:       +41 (32) 720-5720

www.csem.ch      www.vrai.com     ligwww.epfl.ch/matomira.html
From: Steve Gonedes
Subject: Re: categories of constantness
Date: 
Message-ID: <m2hfr3eyfb.fsf@KludgeUnix.com>
"Fernando D. Mato Mira" <········@iname.com> writes:
 
< If you look at things that way, then I prefer it to be called `DEFLITERAL'
< as in ILOG Talk.
< It also appears a bit better in my head regarding the EQL thing: ("Why can't
< I compare something against a _constant_??
< A `literal'? What's do you mean by `literal', precisely?").

Why not use define-symbol-macro as previously mentioned in this
thread? You would probably have to use load-time value for `forms'
though.
From: Vassil Nikolov
Subject: Re: categories of constantness
Date: 
Message-ID: <7drjbm$bbn$1@nnrp1.dejanews.com>
In article <··············@KludgeUnix.com>,
  Steve Gonedes <········@worldnet.att.net> wrote:
>
> "Fernando D. Mato Mira" <········@iname.com> writes:
>
> < If you look at things that way, then I prefer it to be called `DEFLITERAL'
> < as in ILOG Talk.
> < It also appears a bit better in my head regarding the EQL thing: ("Why can't
> < I compare something against a _constant_??
> < A `literal'? What's do you mean by `literal', precisely?").
>
> Why not use define-symbol-macro as previously mentioned in this
> thread? You would probably have to use load-time value for `forms'
> though.

I.e. implement the defining form for *inlined* constants in terms of
DEFINE-SYMBOL-MACRO, possibly assisted by LOAD-TIME-VALUE---is this
what you have in mind?

Maybe this is useful.  One reason why I am uncertain is the time of
day, i.e. night.  Another is that in this way one would _force_
inlining independent of optimisation settings.  (While a compiler
might inline a constant with (OPTIMIZE SPEED (SPACE 0)) and not
inline it with (OPTMIZE SPACE), for example.)  A third is that
if the value of a constant is not a literal object but is to be
evaluated at {compile,load} time, one would want it to be evaluated
just once.  (Correct me if I am wrong but distinct occurrences of
LOAD-TIME-VALUE get each their own evaluation.)

Vassil Nikolov <········@poboxes.com> www.poboxes.com/vnikolov
(You may want to cc your posting to me if I _have_ to see it.)
   LEGEMANVALEMFVTVTVM  (Ancient Roman programmers' adage.)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    
From: Vassil Nikolov
Subject: Re: categories of constantness
Date: 
Message-ID: <7dri9i$aic$1@nnrp1.dejanews.com>
In article <·················@iname.com>,
  "Fernando D. Mato Mira" <········@iname.com> wrote:
>
>
> Vassil Nikolov wrote:
>
> > There is a rough analogy between DEFCONSTANT and a C #define.  (As far
>
> If you look at things that way, then I prefer it to be called `DEFLITERAL'
> as in ILOG Talk.

Changing the name of an existing facility should not be taken lightly
and would need a serious rationale.

> It also appears a bit better in my head regarding the EQL thing: ("Why can't
> I compare something against a _constant_??

You _can_ but you have to pick up the right comparison operator.

Maybe your question is, why can't one always use EQL on constants defined
by DEFCONSTANT, independent of the value (if the value is a number or
symbol or character, you can).  The answer is that this is how DEFCONSTANT
is defined to work, so we come to the question if DEFCONSTANT is doing the
right thing.

I guess this issue is a candidate for debate if there is a future revision
of the standard.  I have mentioned some possibilities in other postings,
and there may be other solutions as well.

> A `literal'? What's do you mean by `literal', precisely?").

There is a definition od `literal object' in the glossary of the standard,
together with some other useful definitions and specifications in the
glossary and the relevant sections.

Vassil Nikolov <········@poboxes.com> www.poboxes.com/vnikolov
(You may want to cc your posting to me if I _have_ to see it.)
   LEGEMANVALEMFVTVTVM  (Ancient Roman programmers' adage.)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own