From: ·········@sneakemail.com
Subject: lambda-returning defmacro, capture
Date: 
Message-ID: <1166009959.022674.224070@j44g2000cwa.googlegroups.com>
Hi, I'm trying to write a macro that (essentially) wraps a lambda ()
around an arbitrary body (it does more than that, but I'm omitting
non-essentials). However,

[2]> (defparameter fff 10)
FFF
[10]> (defmacro mac1 (&rest body) `(lambda () . ,body))
MAC1
[11]> (funcall (let ((fff 11)) (mac1 fff)))
10

(I wanted 11)

Why and what to do? The purpose of the macro is to save typing, in case
you're going to ask.

-- Dan

From: ·······@gmail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166012190.162305.196380@f1g2000cwa.googlegroups.com>
The problem is not related to macros. Try this :

(funcall (let ((fff 11)) (lambda () fff)))

returns 10

The binding of the fff special variable is done at lambda creation and
not at function call.

Try this instead :

(let ((fff 11)) (funcall (mac1 fff)))

returns 11

BB

·········@sneakemail.com wrote:
> Hi, I'm trying to write a macro that (essentially) wraps a lambda ()
> around an arbitrary body (it does more than that, but I'm omitting
> non-essentials). However,
>
> [2]> (defparameter fff 10)
> FFF
> [10]> (defmacro mac1 (&rest body) `(lambda () . ,body))
> MAC1
> [11]> (funcall (let ((fff 11)) (mac1 fff)))
> 10
>
> (I wanted 11)
>
> Why and what to do? The purpose of the macro is to save typing, in case
> you're going to ask.
> 
> -- Dan
From: Andreas Thiele
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <eloqi3$3ck$01$1@news.t-online.com>
<·········@sneakemail.com> schrieb im Newsbeitrag ·····························@j44g2000cwa.googlegroups.com...
> Hi, I'm trying to write a macro that (essentially) wraps a lambda ()
> around an arbitrary body (it does more than that, but I'm omitting
> non-essentials). However,
> 
> [2]> (defparameter fff 10)
> FFF
> [10]> (defmacro mac1 (&rest body) `(lambda () . ,body))
> MAC1
> [11]> (funcall (let ((fff 11)) (mac1 fff)))
> 10
> 
> (I wanted 11)
> 
> Why and what to do? The purpose of the macro is to save typing, in case
> you're going to ask.
> 
> -- Dan
>

Hi Dan,

did you try the following?

CL-USER 32 > (funcall (let ((fff 11)) (lambda () fff)))
10

I think defparameter makes fff dynamic, so the lambda catches the dynamic variable fff. See:

CL-USER 49 > (let ((fff 11)) (funcall (mac1 fff)))
11

My two cent :))

Andreas
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166012767.456630.230970@f1g2000cwa.googlegroups.com>
[ my browser crashed, hope I'm not posting this twice ]

> CL-USER 32 > (funcall (let ((fff 11)) (lambda () fff)))
> 10

Tried it just before I got your reply :)

OK, I've been away from Lisp for a while. Last time I played, I could
use (setq x v) to define a global variable, without implying dynamic
scope. But SBCL warns against using setq to create globals:

* (setq fff 10)
; caught WARNING:
;   undefined variable: FFF

so I figured this style must have been deprecated.

Of course, using setq, the test works as intended.

What's the correct way to define a global without getting dynamic
scope, or SBCL warnings?

-- Dan
From: Rob Warnock
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <V8-dne98COvZa-LYnZ2dnUVZ_v2nnZ2d@speakeasy.net>
<·········@sneakemail.com> wrote:
+---------------
| What's the correct way to define a global without getting
| dynamic scope, or SBCL warnings?
+---------------

While you can perhaps turn off the warning [I think both SBCL
and CMUCL have some variable (not the same name?) you can set
that will suppress it], don't count on being able to turn off
the dynamic scope. In ANSI Common Lisp *all* global variables
are special, that is, have dynamic scope.

But you can fake it. Google for articles about using CL's
DEFINE-SYMBOL-MACRO (usually inside a macro called DEFLEXICAL
or DEFLEX) to define "global lexical variables" which can
then be shadowed by lexical bindings. Here's the simplest
version of it I've seen so far:

    > (defmacro deflex (var val &optional (doc nil docp))    
	(let ((backing-var (make-symbol (symbol-name var))))
	  `(progn
	     (defparameter ,backing-var ,val ,doc)
	     ,@(when docp `((setf (documentation ',var 'variable) ,doc)))
	     (define-symbol-macro ,var ,backing-var))))

    DEFLEX
    > (deflex foo 13)

    FOO
    > (defun foo () foo)

    FOO
    > (let ((foo 234))
	(list foo (foo)))

    (234 13)
    > 

Is that what you're looking for?


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166014573.882912.248110@73g2000cwn.googlegroups.com>
> that will suppress it], don't count on being able to turn off
> the dynamic scope. In ANSI Common Lisp *all* global variables
> are special, that is, have dynamic scope.

Hm. Then why the difference:

[1]> (setq fff 10)
10
[2]> (funcall (let ((fff 11)) (lambda () fff)))
11

vs.

[1]> (defparameter fff 10)
FFF
[2]> (funcall (let ((fff 11)) (lambda () fff)))
10

It seems setq-created globals are less special than
defparameter-created ones. But, again, the SBCL warning seems to
indicate there's something wrong with doing this.

-- Dan
From: Rob Warnock
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <WpKdnUur3ubith_YnZ2dnUVZ_o3inZ2d@speakeasy.net>
<·········@sneakemail.com> wrote:
+---------------
| It seems setq-created globals are less special than
| defparameter-created ones. But, again, the SBCL warning seems to
| indicate there's something wrong with doing this.
+---------------

Indeed. It may work in SBCL today, but since it's undefined behavior
in the standard it's not guaranteed to work in a future version of SBCL.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Rob Warnock
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <UNOdnYQFX9CyzR_YnZ2dnUVZ_ompnZ2d@speakeasy.net>
Oops! Yesterday I wrote this:
+---------------
| [Ise] DEFINE-SYMBOL-MACRO (usually inside a macro called DEFLEXICAL
| or DEFLEX) to define "global lexical variables" which can
| then be shadowed by lexical bindings. Here's the simplest
| version of it I've seen so far:
| 
|     > (defmacro deflex (var val &optional (doc nil docp))    
| 	(let ((backing-var (make-symbol (symbol-name var))))
| 	  `(progn
| 	     (defparameter ,backing-var ,val ,doc)
| 	     ,@(when docp `((setf (documentation ',var 'variable) ,doc)))
| 	     (define-symbol-macro ,var ,backing-var))))
| 
|     DEFLEX
|     > (deflex foo 13)
| 
|     FOO
|     > (defun foo () foo)
| 
|     FOO
|     > (let ((foo 234))
| 	(list foo (foo)))
| 
|     (234 13)
|     > 
+---------------

Turns out that version has a *serious* bug!! I was reading some
old saved articles on this topic, and saw a comment by Tim Bradshaw
noting that a second DEFLEX will generate an expansion to a *new*
uninterned symbol, and that doesn't do what I expect/want at *all*.
Continuing the above example will show the bug:

    > (foo)

    13
    > (deflex foo 54)

    FOO
    > foo

    54
    > (foo)

    13
    > 

I confess that when I said that the above was "the simplest version
of it I've seen so far", I did *not* mean that that's the version I
myself have been using, which is quite a bit uglier [see "p.s." below].
I thought the above was cute and short, but clearly didn't think it
through far enough.  Mea culpa.

Here's an equally-short one based on what I've seen in this recent
thread. I *don't* know that it works reliably, either, but it passes
a few quick tests:

    > (defmacro deflex (var val &optional (doc nil docp))    
	`(progn
	   (locally (declare (special ,var))
	     (setf (symbol-value ',var) ,val))
	   ,@(when docp `((setf (documentation ',var 'variable) ,doc)))
	   (define-symbol-macro ,var (symbol-value ',var))))

    DEFLEX
    > (deflex foo 13)

    FOO
    > (defun foo () foo)

    FOO
    > (let ((foo 234))
        (list foo (foo)))

    (234 13)
    > (setf foo 24)

    24
    > (let ((foo 234))
        (list foo (foo)))

    (234 24)
    > (deflex foo 57)

    FOO
    > (let ((foo 234))
        (list foo (foo)))

    (234 57)
    > 

That's better!!  ;-}

[Caveat: This version blows up in an ancient CLISP (ver. 2.29)
with a stack overflow, but seems to work o.k. in CMUCL.]


-Rob

p.s. And just in case the *second* version has some hidden flaw,
here's the really ugly version that I've actually been using myself
for years:

(defmacro deflex (var val &optional (doc nil docp))    
  (let ((backing-var (intern (concatenate 'string
					  (symbol-name '#:*deflex-var-)
					  (symbol-name var)
					  (symbol-name '#:*))
	                     (symbol-package var)))) ; <== Important!
    `(progn
       (defparameter ,backing-var ,val ,doc)
       ,@(when docp `((setf (documentation ',var 'variable) ,doc)))
       (define-symbol-macro ,var ,backing-var))))

p.p.s. Note that there's a long-standing problem in CMUCL with
DEFINE-SYMBOL-MACRO expansion, that fails no matter which of
the above you use. If FOO is a symbol macro that has been shadowed
by a local (LET ((FOO ...) ...), then (SETF FOO xyz) works fine
[that is, changes the innermost FOO] but (INCF FOO) increments
the *outer* FOO!  There's been a fix for that in SBCL for about
a year, and one of the CMUCL maintainers is working get something
similar into CMUCL "real soon now". But for the moment, if you're
using CMUCL be careful about SETF-expanders (other than plain SETQ/SETF)
on symbol macros.

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: ·······@gmail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166324334.569072.234980@79g2000cws.googlegroups.com>
Rob Warnock wrote:
> p.p.s. Note that there's a long-standing problem in CMUCL with
> DEFINE-SYMBOL-MACRO expansion, that fails no matter which of
> the above you use. If FOO is a symbol macro that has been shadowed
> by a local (LET ((FOO ...) ...), then (SETF FOO xyz) works fine
> [that is, changes the innermost FOO] but (INCF FOO) increments
> the *outer* FOO!  There's been a fix for that in SBCL for about
> a year, and one of the CMUCL maintainers is working get something
> similar into CMUCL "real soon now". But for the moment, if you're
> using CMUCL be careful about SETF-expanders (other than plain SETQ/SETF)
> on symbol macros.

Thanks Rob. It sounds like symbol macros aren't settled and are subject
to bugs in some implementations. Then there's the proliferation of
multiple deflex macros, each with its own problems.

Also, if there are multiple source files, are the backing variables
going to be the same? I confess I don't quite undestand packages yet.

Dan
From: Rob Warnock
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <3qKdnRF8hLf7pxjYnZ2dnUVZ_tijnZ2d@speakeasy.net>
<·······@gmail.com> wrote:
+---------------
| Rob Warnock wrote:
| > p.p.s. Note that there's a long-standing problem in CMUCL with
| > DEFINE-SYMBOL-MACRO expansion, that fails no matter which of
| > the above you use. ...
| 
| Thanks Rob. It sounds like symbol macros aren't settled and are
| subject to bugs in some implementations.
+---------------

Symbol macros *are* "settled": they're in ANSI Common Lisp:

    http://www.alu.org/HyperSpec/Body/mac_define-symbol-macro.html
    http://www.alu.org/HyperSpec/Body/speope_symbol-macrolet.html

Remember, Common Lisp is defined by the ANSI standard, *not* by
any particular implementation, and *especially* not by the bugs
and/or standards-conformance issues of any particular implementation.

The bug in CMUCL is understood, and a fix is in progress. There is
no reason to avoid symbol macros unless you both must use CMUCL
*and* cannot wait for a fix. [If you want to fix it yourself, the
problem is in "src/code/eval.lisp", in the function MACROEXPAND-1.
If you compare the first COND there with the similar one in the
MACRO-FUNCTION function just above, the fix may be obvious.]
If you're using any other implementation of CL, it probably
works fine.

+---------------
| Then there's the proliferation of multiple deflex macros...
+---------------

This statement verges on FUD. Since DEFLEX is not part of the
standard, of *course* there are multiple versions. But that's
no different than any other useful abstraction that is not part
of the standard, such as socket libraries.

+---------------
| ...each with its own problems.
+---------------

As far as I know, there are two main approaches which work just
fine across implementations: One expands FOO to #.(MANGLE-NAME 'FOO)
[for some choice of #'MANGLE-NAME) and uses DEFPARAMETER to set
the initial value of #.(MANGLE-NAME 'FOO); the other expands FOO
to (SYMBOL-VALUE 'FOO) and uses the (LOCALLY (SPECIAL FOO) (SETF
(SYMBOL-VALUE 'FOO) ...)) hack to set the initial value. I personally
have always used the first, because on the implementation I use most
[CMUCL] it generates slightly better code than the second. But YMMV.

There was *one* erroneous approach [expand FOO to #:FOO] which I
mistakenly presented in an earlier posting because I forgot that
it breaks separate compilation. My apologies for any confusion
generated by that.

+---------------
| Also, if there are multiple source files, are the backing variables
| going to be the same?
+---------------

For both of the above working approaches, yes. But to make it truly
useful in that case you will need a separate version of the macro
[definition of which is left as an exercise for the reader] that
doesn't initialize the variable, but only defines the symbol macro.
I myself have only ever had to do this once, but it sounds like your
application might need it more.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166364701.312360.92240@79g2000cws.googlegroups.com>
> +---------------
> | Then there's the proliferation of multiple deflex macros...
> +---------------
>
> This statement verges on FUD. Since DEFLEX is not part of the
> standard, of *course* there are multiple versions. But that's
> no different than any other useful abstraction that is not part
> of the standard, such as socket libraries.

Sorry, didn't mean to sound that way. But to give you a little context
-- I'm having a hard time explaining this whole thread to other
developers involved in the project, and conveying any feeling of
confidence... firstly, I don't entirely understand what's going on
(yet); secondly, you found a bug in your first version -- and then
provided two more versions, one of which you characterized as "I
*don't* know that it works reliably, either, but it passes a few quick
tests". Untill I completely grok symbol macros and packages I am still
worried.

(btw, I don't mean to come out as ungrateful -- thank you for taking
the time to respond -- I'm just saying I feel outside my "comfort
zone")

Another question: can I

(defun f (x) (+ *global* x))

and only then declare *global*  with deflex? Contrary to my intuition
(which is that macroexpansion takes place when the defun is read) this
does seem to work in SBCL.
From: Rob Warnock
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <75WdnVkSW_GAEBvYnZ2dnUVZ_oS3nZ2d@speakeasy.net>
<·········@sneakemail.com> wrote:
+---------------
| > +---------------
| > | Then there's the proliferation of multiple deflex macros...
| > +---------------
| >
| > This statement verges on FUD. Since DEFLEX is not part of the
| > standard, of *course* there are multiple versions. But that's
| > no different than any other useful abstraction that is not part
| > of the standard, such as socket libraries.
| 
| Sorry, didn't mean to sound that way. But to give you a little context
| -- I'm having a hard time explaining this whole thread to other
| developers involved in the project, and conveying any feeling of
| confidence... firstly, I don't entirely understand what's going on
| (yet); secondly, you found a bug in your first version -- and then
| provided two more versions, one of which you characterized as "I
| *don't* know that it works reliably, either, but it passes a few quick
| tests". Untill I completely grok symbol macros and packages I am still
| worried.
+---------------

To give you a little context as well, if I remember the order
correctly the "first" [expands to uninterned symbol] and "second"
[expands to SYMBOL-VALUE call] versions of DEFLEX were things
I posted in the long sub-thread about the hack of using LOCALLY
to avoid declaring a variable globally special. That whole sub-thread
was sort of wild & wooly, IMHO, and my contributions were as
half-baked as anyone else's, but were attempts to show how the
LOCALLY hack might help provide a DEFLEX definition that was
considerably shorter/simpler than the usual mangled-named version.
Obviously, my first try was *too* simple, but the second should
probably work fine [though I have no long experience with it].

The chronologically "third" version of DEFLEX [expands to mangled-named
and declared special variables] -- that was in the "p.s." of the message
with the second one in it -- is actually the one I have been using for
several years, and the one in which I therefore have the most confidence.
[Especially now that the CMUCL bug has finally been found/fixed -- see
my just-posted patch!] The third version also generates better code
*in CMUCL* than the second. To repeat it again:

(defmacro deflex (var val &optional (doc nil docp))    
  (let ((backing-var (intern (concatenate 'string
                                          (symbol-name '#:*deflex-var-)
                                          (symbol-name var)
                                          (symbol-name '#:*))
                             (symbol-package var))))
    `(progn
       (defparameter ,backing-var ,val ,doc)
       ,@(when docp `((setf (documentation ',var 'variable) ,doc)))
       (define-symbol-macro ,var ,backing-var))))

+---------------
| Another question: can I
|   (defun f (x) (+ *global* x))
| and only then declare *global*  with deflex? Contrary to my intuition
| (which is that macroexpansion takes place when the defun is read) this
| does seem to work in SBCL.
+---------------

Several things about that seem rather questionable to me, though since
I don't use SBCL at all perhaps I'm probably not the best person to
address this:

1. In ANSI Common Lisp, macros need to be defined before they
   are referenced. See CLHS 3.2.2.3 "Semantic Constraints" and
   also 3.1.2.1.1 "Symbols as Forms":

      The symbol names a symbol macro if there is a binding of the
      symbol as a symbol macro in the current lexical environment...

   Thus, in general, you would need to DEFLEX any such variables
   *before* their first use.

2. I thought SBCL compiled eveything as it was entered. If so, why
   didn't it complain about the undefined free variable? CMUCL will
   certainly complain about it if you compile F:

      cmu> (compile *)
      ; Compiling LAMBDA (X): 
      ; Compiling Top-Level Form: 

      ; In: LAMBDA (X)

      ;   (+ *GLOBAL* X)
      ; Warning: Undefined variable *GLOBAL*
      ...[trimmed]...

3. In CMUCL, at least, doing a (DEFLEX *GLOBAL* 37) *after* F has been
   compiled certainly does *NOT* work [and I wouldn't expect it to]:

      cmu> (deflex *global* 37)

      *GLOBAL*
      cmu> (f 12)

      Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER:  the variable *GLOBAL* is unbound.
	 [Condition of type UNBOUND-VARIABLE]
      ...[trimmed]...

   It will sometimes "work" (*unreliably!!*) in CMUCL if, when
   the DEFLEX is done, the function has not yet been compiled
   *or* "converted", an internal CMUCL operation in which a function
   is "half-compiled" [including macroexpansion] into the form used
   by the interpreter. I said "unreliably", because such "conversion"
   [and the attendant macroexpansion] can be triggered even if the
   function is never called, simply by appearing in a position where
   it *might* be called, e.g.:

      cmu> (defun f (x) (+ *global* x))

      F
      cmu> (if nil (f 13) 456)
      ; 
      ; Warning: This variable is undefined:
      ;   *GLOBAL*
      ; 
      456
      cmu> 

   Doing a DEFLEX of *GLOBAL* after this "conversion" has occurred
   will not prevent an error if F is subsequently called.

4. IMHO the *VAR* convention should be reserved for variables which
   are declared to be special, and *not* used for "global lexicals".
   Doing so will seriously confuse a Lisp-aware reader. Besides, the
   whole *point* of DEFLEX is to allow one to safely used undistinguished
   names without worrying about accidentally forcing dynamic scope on
   some inner binding.

Summing up: No, you should not count on being able to define functions
which reference undefined free variables which you *later* define as
symbol macros (e.g., with DEFLEX or equiv.).


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Rob Warnock
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <Y_Cdnbvi_4Ir4RvYnZ2dnUVZ_tunnZ2d@speakeasy.net>
Yesterday, I wrote:
+---------------
| The [symbol macro] bug in CMUCL is understood, and a fix is in progress.
| There is no reason to avoid symbol macros unless you both must use CMUCL
| *and* cannot wait for a fix. [If you want to fix it yourself, the
| problem is in "src/code/eval.lisp", in the function MACROEXPAND-1.
| If you compare the first COND there with the similar one in the
| MACRO-FUNCTION function just above, the fix may be obvious.]
+---------------

Just so everyone knows, the modified version of MACROEXPAND-1
[attached below -- the change is in the first branch of the COND]
has been submitted to one of the CMUCL developers, who assures me
that it will be in the CVS tree "real soon now". Meanwhile, you
can compile/load this version into your copy of CMUCL-19c (wrap a
WITHOUT-PACKAGE-LOCKS around the LOAD) and the bug will go away.
Here's a test case:

    > (defvar *foo* 13)    

    *FOO*
    > (define-symbol-macro foo *foo*)

    FOO
    > (defun foo () foo)

    FOO
    > (let ((foo 57))
        (list foo (incf foo) foo (foo)))

    (57 58 58 13)
    > 

Without the patch, you'll get (57 14 57 14).


-Rob

-----
Rob Warnock                     <····@rpw3.org>
627 26th Avenue                 <URL:http://rpw3.org/>
San Mateo, CA 94403             (650)572-2607

======= attachment: extracted from $CMUCL/src/code/eval.lisp ==============
(in-package "LISP")

;;; Macroexpand-1  --  Public
;;;
;;;    The Env is a LEXENV or NIL (the null environment.)
;;;
(defun macroexpand-1 (form &optional env)
  "If form is a macro (or symbol macro), expands it once.  Returns two values,
   the expanded form and a T-or-NIL flag indicating whether the form was, in
   fact, a macro.  Env is the lexical environment to expand in, which defaults
   to the null environment."
  (cond ((and (consp form) (symbolp (car form)))
         (let ((def (macro-function (car form) env)))
           (if def
               (values (invoke-macroexpand-hook def form env) t)
               (values form nil))))
        ((symbolp form)
         (let* ((venv (when env (c::lexenv-variables env)))
                (local-def (cdr (assoc form venv))))
           (cond (local-def
                   (if (and (consp local-def)
                            (eq (car local-def) 'macro))
                     (values (cdr local-def) t)
                     (values form nil)))
                 ((eq (info variable kind form) :macro)
                  (values (info variable macro-expansion form) t))
                 (t
                  (values form nil)))))
        (t
         (values form nil))))
From: Andreas Thiele
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <elotlu$f4c$00$1@news.t-online.com>
<·········@sneakemail.com> schrieb im Newsbeitrag ·····························@f1g2000cwa.googlegroups.com...
>[ my browser crashed, hope I'm not posting this twice ]
> 
>> CL-USER 32 > (funcall (let ((fff 11)) (lambda () fff)))
>> 10
> 
> Tried it just before I got your reply :)
> 
> OK, I've been away from Lisp for a while. Last time I played, I could
> use (setq x v) to define a global variable, without implying dynamic
> scope. But SBCL warns against using setq to create globals:
> 
> * (setq fff 10)
> ; caught WARNING:
> ;   undefined variable: FFF
> 
> so I figured this style must have been deprecated.
> 
> Of course, using setq, the test works as intended.
> 
> What's the correct way to define a global without getting dynamic
> scope, or SBCL warnings?
> 
> -- Dan
>

Dan,

I think setq is not recommendable style anymore because setf is more general AFAIR. Recently this was discussed here.

I am not 100% sure but I think all global variables are special, meaning dynamic. I think this has to to with their environment. 

Helpful might be:

http://www.flownet.com/gat/specials.pdf

Andreas
From: Andreas Thiele
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <elotlv$f4c$00$2@news.t-online.com>
<·········@sneakemail.com> schrieb im Newsbeitrag ·····························@f1g2000cwa.googlegroups.com...
>[ my browser crashed, hope I'm not posting this twice ]
> 
>> CL-USER 32 > (funcall (let ((fff 11)) (lambda () fff)))
>> 10
> 
> Tried it just before I got your reply :)
> 
> OK, I've been away from Lisp for a while. Last time I played, I could
> use (setq x v) to define a global variable, without implying dynamic
> scope. But SBCL warns against using setq to create globals:
> 
> * (setq fff 10)
> ; caught WARNING:
> ;   undefined variable: FFF
> 
> so I figured this style must have been deprecated.
> 
> Of course, using setq, the test works as intended.
> 
> What's the correct way to define a global without getting dynamic
> scope, or SBCL warnings?
> 
> -- Dan
>

Dan,

I think setq is not recommendable style anymore because setf is more general AFAIR. Recently this was discussed here.

I am not 100% sure but I think all global variables are special, meaning dynamic. I think this has to to with their environment. 

Helpful might be:

http://www.flownet.com/gat/specials.pdf

Andreas
From: Rob Warnock
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <WpKdnUir3uZgtx_YnZ2dnUVZ_o2vnZ2d@speakeasy.net>
Andreas Thiele <········@nospam.com> wrote:
+---------------
| <·········@sneakemail.com> schrieb:
| > What's the correct way to define a global without getting dynamic
| > scope, or SBCL warnings?
...
| I am not 100% sure but I think all global variables are special, meaning
| dynamic. I think this has to to with their environment. 
| Helpful might be:
|    http://www.flownet.com/gat/specials.pdf
+---------------

Also helpful is KMP's writeup of "FAILED Issue PROCLAIM-LEXICAL"
(a reference to which is found in Ron's excellent little paper above):

    http://www.nhplace.com/kent/CL/Issues/proclaim-lexical.html

The CL committee struggled over if/how to add "global lexicals"
and, in the end, simply punted. Actually, they *did* provide one out,
the DEFINE-SYMBOL-MACRO macro, which can be used to provide the
*appearance* of global lexicals, see:

    http://www.alu.org/HyperSpec/Body/03_abaa.htm
    3.1.2.1.1 Symbols as Forms

    http://www.alu.org/HyperSpec/Body/m_defi_1.htm#define-symbol-macro
    Macro DEFINE-SYMBOL-MACRO
    ...
    A binding for a symbol macro can be shadowed by
    LET or SYMBOL-MACROLET.

    http://www.alu.org/HyperSpec/Issues/iss198_w.htm
    Issue ISO-COMPATIBILITY Writeup
    ...
    Rationale:
    ...
      1. DEFINE-SYMBOL-MACRO can be used to define global lexicals,
      by having a global lexical be a symbol macro that expands
      into a reference to a globally allocated cell that is not
      subject to dynamic binding.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <87d56orl6h.fsf@thalassa.informatimago.com>
·········@sneakemail.com writes:

> [ my browser crashed, hope I'm not posting this twice ]
>
>> CL-USER 32 > (funcall (let ((fff 11)) (lambda () fff)))
>> 10
>
> Tried it just before I got your reply :)
>
> OK, I've been away from Lisp for a while. Last time I played, I could
> use (setq x v) to define a global variable, without implying dynamic
> scope. But SBCL warns against using setq to create globals:
>
> * (setq fff 10)
> ; caught WARNING:
> ;   undefined variable: FFF
>
> so I figured this style must have been deprecated.
>
> Of course, using setq, the test works as intended.
>
> What's the correct way to define a global without getting dynamic
> scope, or SBCL warnings?

Well, that's the point: there is no _standard_ way to define a global
non-dynamic variable.

So, it seems that both sbcl and clisp allow defining global "lexical"
variables with SETF/SETQ.  But this is no standard Common Lisp.


(Perhaps it would be better to have a EXT:DEFGLOBAL macro to define
global lexical variables than to overload a standard operator like
CL:SETQ?).


So, what you should write, if you want to write standard Common Lisp, is:


    (let ((fff 10))

      (print   
        (let ((fff 11))
           (funcall (lambda  () fff))))

      (print   
        (funcall (let ((fff 11))
                    (lambda  () fff))))

      (values))

prints:

    11
    11

and:

    (let ((fff 10))

      (print   
        (let ((fff 11))
           (funcall (mac1 fff))))

      (print   
        (funcall (let ((fff 11))
                    (mac1 fff))))

      (values))

prints:

    11 
    11 


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166016615.101221.86380@80g2000cwy.googlegroups.com>
Thanks everybody. Andreas, the PDF reference had the answer I was
looking for.

The problem isn't dynamic vs. lexical scope. The problem is that
(defvar fff ...) and (defparameter) not only declare a variable as
special, but also pervasively declare all future references and
bindings for fff to be special. Yes, that includes future (let ((fff
...)) ...) bindings. No, that's not what we want.

The way to declare a special global variable, without making it
*pervasively* special, is

(locally (declare (special fff)) (setq fff 10))

issued in the top environment. Works right, and does not make SBCL
scream.

Supposedly, a naked (setq) does the same thing in SBCL and clisp, but
in CMUCL, it implies defvar.

I can't help but remark that the syntax, semantics, and verbosity are
disgusting (just like in many other instances with Common Lisp). Oh
well.

-- Dan
From: Zach Beane
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <m364cfapg2.fsf@unnamed.xach.com>
·········@sneakemail.com writes:

> The problem isn't dynamic vs. lexical scope. The problem is that
> (defvar fff ...) and (defparameter) not only declare a variable as
> special, but also pervasively declare all future references and
> bindings for fff to be special. Yes, that includes future (let ((fff
> ...)) ...) bindings. No, that's not what we want.

That's why global specials are, by convention, surrounded by
asterisks, and some lisps will go so far as to give you a helpful
style warning when you bind a variable that looks like a special but
isn't.

Zach
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166017703.575738.163740@j72g2000cwa.googlegroups.com>
> That's why global specials are, by convention, surrounded by
> asterisks, and some lisps will go so far as to give you a helpful
> style warning when you bind a variable that looks like a special but

Right. But I have a different use case than the conventional one. It
shouldn't take that convoluted (locally (declare (special ...)))
nonsense just to get a non-pervasive special global. Or at least it
should be easier to find out about this junk. It's amazing that no-one
had this bit of information in "active memory", and I had to go digging
in some random PDF tutorial just to understand something so basic.

OK, I'm going to calm down now :)
From: Joel Wilsson
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166021246.010965.223480@79g2000cws.googlegroups.com>
·········@sneakemail.com wrote:
> But I have a different use case than the conventional one.

You use a feature you didn't understand (dynamic variables) in an
unconventional way, and now you're surprised and angry that it bit
you. Dynamic variables are uncommon and special, that it is why
they are given special names. You didn't give your dynamic variables
special names, and so you forgot they were special.

The "obscure PDF" you refer to is linked to in the first hit on Google:
http://www.google.com/search?q=common+lisp+special+variables

There's also an explanation of how this works in Practical Common
Lisp, chapter 6.  The example given there would also have been
sufficient for you to understand the issues involved, if you had
tried to do so.
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166021946.109343.271460@79g2000cws.googlegroups.com>
> You use a feature you didn't understand (dynamic variables) in an
> unconventional way, and now you're surprised and angry that it bit
> you.

Joel, I understand dynamic variables. Normal dynamic scope doesn't have
the weird effect I showed in the OP. Only the pervasiveness of defvar
can cause that. Did you follow the thread?

As far as surprise -- I'm surprised that (defun) doesn't have a simple
equivalent for the symbol-value slot. Don't you think some amount of
design symmetry would have been nice?

> Dynamic variables are uncommon and special, that it is why
> they are given special names. You didn't give your dynamic variables
> special names, and so you forgot they were special.

Uh, no. I didn't realize that (defvar) had the pervasive effect. That's
all.

> There's also an explanation of how this works in Practical Common
> Lisp, chapter 6.  The example given there would also have been
> sufficient for you to understand the issues involved, if you had
> tried to do so.

Right. If it was so obvious, how come none of the regulars could point
out the pervasive effect of defvar as being the cause of the problem
(with some posters quite off-mark)? Again, dynamic scope is not
sufficient to cause the original problem.
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <87vekfptbm.fsf@thalassa.informatimago.com>
·········@sneakemail.com writes:

>> You use a feature you didn't understand (dynamic variables) in an
>> unconventional way, and now you're surprised and angry that it bit
>> you.
>
> Joel, I understand dynamic variables. Normal dynamic scope doesn't have
> the weird effect I showed in the OP. Only the pervasiveness of defvar
> can cause that. Did you follow the thread?
>
> As far as surprise -- I'm surprised that (defun) doesn't have a simple
> equivalent for the symbol-value slot. Don't you think some amount of
> design symmetry would have been nice?

It is nice, and DEFUN has it.  It's called defparameter.

But where the symetry breaks is that flet/labels bind always a
lexical function, never a "dynamic" function.  

So your rationalization doesn't work here...



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

This universe shipped by weight, not volume.  Some expansion may have
occurred during shipment.
From: Kaz Kylheku
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166167749.366236.39180@79g2000cws.googlegroups.com>
·········@sneakemail.com wrote:
> equivalent for the symbol-value slot. Don't you think some amount of
> design symmetry would have been nice?

In the other direction: pervasively special, dynamically scoped
functions.

Pascal Costanza has done work in this direction.

> Right. If it was so obvious, how come none of the regulars could point
> out the pervasive effect of defvar as being the cause of the problem
> (with some posters quite off-mark)?

Why, because the staggeringly rising popularity of Lisp is diluting the
old guard with a vast army of neophytes.
From: Thomas A. Russ
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <ymiwt4vk5fm.fsf@sevak.isi.edu>
·········@sneakemail.com writes:


> Right. But I have a different use case than the conventional one.

So it really shouldn't be too surprising that you don't have built-in
tools to support what you want to do.  You are doing something not
really envisioned by the language design, so you don't have a simple way
to do things.

But I still don't understand why you need the global value if you are
lexically binding the variable name when you want to use it.  In other
words, I don't understand why you need

   (funcall (let ((fff 11)) (mac1 fff)) ...)

instead of

   (let ((fff 11)) (funcal (mac1 fff) ...))

and just use the dynamic binding scope.

But as for this:

>  It
> shouldn't take that convoluted (locally (declare (special ...)))
> nonsense just to get a non-pervasive special global.

Well, at least it is easy to fix the convoluted part with macros:

(defmacro defglobal (sym value)
 "Defines a global variable that is not proclaimed special."n
 `(locally (declare (special ,sym)) (setq ,sym ,value)))

(defglobal fff)

But I really don't see a lot of use for this feature, since in order to
get the special value, you need to remember to wrap the lexical
reference to "fff" with a (declare (special fff)).  At that point you
are essentially manually managing the places where you want to have the
special value and where you want to have the lexical value.

One you make the step to deciding that you have two different variables
that are now confusingly named the same, it becomes clear that a better
design would be to introduce separate names for these two variables and
recast your original problem like:

(defparameter *foo* 10)

(defmacro mac1 (sym) `(lambda () ,sym))

(funcall (let ((fff 11)) (mac1 fff)))

and just use the different names.  Just because you can overload the
names, doesn't mean that it's a good idea.

Now, I'm sure you have a much larger problem that your design helps
solve, but I'm not sure what it is you want the globally visible, but
not pervasive special declaration to buy you.

Without a global special declaration, most lisps will warn you if you
have a free reference to an undeclared variable.  Most lisps will also
assume that such references are supposed to be to special variables, but
this is not mandated by the standard.  And you should not be trying to
exploit this general behavior to let you provide a value when you
reference this global variable outside of a lexical scope, but without a
local definition of it being special.


>  Or at least it
> should be easier to find out about this junk. It's amazing that no-one
> had this bit of information in "active memory", and I had to go digging
> in some random PDF tutorial just to understand something so basic.

Well, you only run into issues when you return a function out of a
binding block where the variables have dynamic scope instead of
lexical.  So it is a pretty rare sort of thing to be doing, and thus it
doesn't particularly surprise me that it is a bit obscure.

I do, however, miss having something like a "notspecial" declaration to go
along with the "special" declaration.  I can't imagine that it would
impose any significant implementation burden....

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <87wt4vrj0e.fsf@thalassa.informatimago.com>
·········@sneakemail.com writes:

> Thanks everybody. Andreas, the PDF reference had the answer I was
> looking for.
>
> The problem isn't dynamic vs. lexical scope. The problem is that
> (defvar fff ...) and (defparameter) not only declare a variable as
> special, but also pervasively declare all future references and
> bindings for fff to be special. Yes, that includes future (let ((fff
> ...)) ...) bindings. No, that's not what we want.
>
> The way to declare a special global variable, without making it
> *pervasively* special, is
>
> (locally (declare (special fff)) (setq fff 10))
>
> issued in the top environment. Works right, and does not make SBCL
> scream.

I'm not sure that as a toplevel form it has a standard meaning.  I don't know.

Is a mere  (declare (special fff)) enough  to define a variable?

I'd use (let ((fff 10)) (declare (special fff)) ...)


> Supposedly, a naked (setq) does the same thing in SBCL and clisp, but
> in CMUCL, it implies defvar.
>
> I can't help but remark that the syntax, semantics, and verbosity are
> disgusting (just like in many other instances with Common Lisp). Oh
> well.

Well, global variables are bad anyways.  So it's a good thing that
they be ugly to declare...

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"This machine is a piece of GAGH!  I need dual Opteron 850
processors if I am to do battle with this code!"
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166019548.616158.59130@f1g2000cwa.googlegroups.com>
> Well, global variables are bad anyways.  So it's a good thing that
> they be ugly to declare...

Right, Pascal. If you hadn't gotten it wrong the first time around,
maybe this statement would be less ridiculous. No wait, it wouldn't.

Do you realize that this is merely the equivalent of (defun) for the
symbol-value slot?

But, why be objective? If you try hard enough you might be able to come
up with a few more rationalization pearls like your last one.
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <87zm9rptgc.fsf@thalassa.informatimago.com>
·········@sneakemail.com writes:

>> Well, global variables are bad anyways.  So it's a good thing that
>> they be ugly to declare...
>
> Right, Pascal. If you hadn't gotten it wrong the first time around,
> maybe this statement would be less ridiculous. No wait, it wouldn't.

What have I got wrong?


> Do you realize that this is merely the equivalent of (defun) for the
> symbol-value slot?

Not exactly and not necessarily.


> But, why be objective? If you try hard enough you might be able to come
> up with a few more rationalization pearls like your last one.

?


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
The mighty hunter
Returns with gifts of plump birds,
Your foot just squashed one.
From: Lars Rune Nøstdal
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <pan.2006.12.13.15.48.44.101287@gmail.com>
On Wed, 13 Dec 2006 05:30:15 -0800, to9sn2r02 wrote:

> (locally (declare (special fff)) (setq fff 10))
> 
> issued in the top environment. Works right, and does not make SBCL
> scream.
.. 
> I can't help but remark that the syntax, semantics, and verbosity are
> disgusting  ...

.. maybe you should go back to C++ then .. :}

"Always special" globals usually does the right thing - for me at least;
they have turned out to be a great feature. But I don't think this
is too bad considering what's going on and how seldom one (well I) need
this:


  (defmacro defnvar (name &optional val)
    `(locally (declare (special ,name))
       (setq ,name ,val)
       ',name))


  (defmacro as-specials (vars &body body)
    `(locally (declare (special ,@vars))
       ,@body))
  

  (defnvar morphed 'special-value)


  (defmacro as-function (&body body)
    `(lambda () ,@body))



  (defun test1 ()
    (let ((morphed 'lexical-value))
      (list
       morphed
       (as-specials (morphed)
         morphed))))


  (defun test2 ()
    (list
     (funcall (let ((morphed 'lexical-value))
                (as-function morphed)))
     (funcall (let ((morphed 'lexical-value))
                (as-specials (morphed)
                  (as-function morphed))))))
     
  

#|
cl-user> (list (test1) (test2))
((lexical-value special-value) (lexical-value special-value))
|#

..not sure I got this right; I'm tired.

-- 
Lars Rune Nøstdal
http://nostdal.org/
From: Alex Mizrahi
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <45804ee6$0$49207$14726298@news.sunsite.dk>
(message (Hello 'Pascal)
(you :wrote  :on '(Wed, 13 Dec 2006 14:15:50 +0100))
(

 PB> Well, that's the point: there is no _standard_ way to define a global
 PB> non-dynamic variable.

 PB> So, it seems that both sbcl and clisp allow defining global "lexical"
 PB> variables with SETF/SETQ.  But this is no standard Common Lisp.

i wonder what's wrong with this:

CG-USER(1): (setf (symbol-value 'varr) 10)
10
CG-USER(2): (funcall (let ((varr 11)) (lambda () varr)))
11
CG-USER(3): varr
10

ain't that "global non-dynamic variable"?

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"People who lust for the Feel of keys on their fingertips (c) Inity") 
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166038885.462454.17490@80g2000cwy.googlegroups.com>
>  PB> Well, that's the point: there is no _standard_ way to define a global
>  PB> non-dynamic variable.
>
>  PB> So, it seems that both sbcl and clisp allow defining global "lexical"
>  PB> variables with SETF/SETQ.  But this is no standard Common Lisp.

Pascal, this is where you were wrong. (1) There is a standard way, and
(2) setq defines a global special (not lexical) variable. The standard
way is (locally (declare (special fff)) (setq fff 10)).

Also, (3) defparameter makes the name pervasively dynamic, just like
defvar. So neither defvar nor defparameter provide the symmetric
counterpart to defun.

Still, sorry for my tone.

> CG-USER(1): (setf (symbol-value 'varr) 10)
> 10
> CG-USER(2): (funcall (let ((varr 11)) (lambda () varr)))
> 11
> CG-USER(3): varr
> 10

Alex: supposedly that's not correct, though the setf + symbol-value
combination appears in many places in reputable references. I assume
that it needs a preceeding (defvar) to be valid.
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <8764cfpmdf.fsf@thalassa.informatimago.com>
·········@sneakemail.com writes:

>>  PB> Well, that's the point: there is no _standard_ way to define a global
>>  PB> non-dynamic variable.
>>
>>  PB> So, it seems that both sbcl and clisp allow defining global "lexical"
>>  PB> variables with SETF/SETQ.  But this is no standard Common Lisp.
>
> Pascal, this is where you were wrong. (1) There is a standard way, and
> (2) setq defines a global special (not lexical) variable. The standard
> way is (locally (declare (special fff)) (setq fff 10)).

Well I admit that it works.  
It seems to have the same effects as (setf (symbol-value 'fff) 10).

In both cases, I don't understand why the value can be accessed
directly by fff in the global environment, as in the global
environment without a special declaration, fff seems to be no
variable.


(locally (declare (special fff))
    ;; here, fff is a dynamic variable.
    (setq fff 10))

;; here, fff is not a dynamic variable. 
;; Why evaluating:

fff

;; should return 10 ?



> Also, (3) defparameter makes the name pervasively dynamic, just like
> defvar. So neither defvar nor defparameter provide the symmetric
> counterpart to defun.
>
> Still, sorry for my tone.
>
>> CG-USER(1): (setf (symbol-value 'varr) 10)
>> 10
>> CG-USER(2): (funcall (let ((varr 11)) (lambda () varr)))
>> 11
>> CG-USER(3): varr
>> 10
>
> Alex: supposedly that's not correct, though the setf + symbol-value
> combination appears in many places in reputable references. I assume
> that it needs a preceeding (defvar) to be valid.



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

WARNING: This product warps space and time in its vicinity.
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166052104.962033.251830@79g2000cws.googlegroups.com>
> (locally (declare (special fff))
>     ;; here, fff is a dynamic variable.
>     (setq fff 10))
>
> ;; here, fff is not a dynamic variable.
> ;; Why evaluating:
>
> fff
>
> ;; should return 10 ?

It seems that dynamic variables spring into existence when assigned to;
this is even more strange:

(defun tst () (locally (declare (special fff)) (setq fff 10)))
(tst)
fff
;; => 10


Reading the PDF, I took this behavior for granted, but after this
discussion, I'm confused. Once more, Common Lisp has ambiguities and
complexities even in some of its very basic building blocks. This is
ridiculous. Even more ridiculous is that people seem to put up with it
with a wide grin. Anyway...

Is there at least any consensus on how to create a non-pervasive
dynamic global? That would be enough for my purposes. Can anyone
confirm that (locally (declare...) (setq ...) is correct?

'(|Dan|)
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <87psannxwt.fsf@thalassa.informatimago.com>
·········@sneakemail.com writes:

>> (locally (declare (special fff))
>>     ;; here, fff is a dynamic variable.
>>     (setq fff 10))
>>
>> ;; here, fff is not a dynamic variable.
>> ;; Why evaluating:
>>
>> fff
>>
>> ;; should return 10 ?
>
> It seems that dynamic variables spring into existence when assigned to;
> this is even more strange:
>
> (defun tst () (locally (declare (special fff)) (setq fff 10)))
> (tst)
> fff
> ;; => 10
>
>
> Reading the PDF, I took this behavior for granted, but after this
> discussion, I'm confused. Once more, Common Lisp has ambiguities and
> complexities even in some of its very basic building blocks. This is
> ridiculous. Even more ridiculous is that people seem to put up with it
> with a wide grin. Anyway...
>
> Is there at least any consensus on how to create a non-pervasive
> dynamic global? 

Well, the consensus is that we just don't.

Either we create a global special variable that we carefully name with
stars to distinguish it as a global special variable:

    (defparameter *var* <init-form> "documentation")

    ...

or we use lexical variables:

    (let ((var <init-form>))
       ...)


> That would be enough for my purposes. Can anyone
> confirm that (locally (declare...) (setq ...) is correct?

What purpose is it?


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

CAUTION: The mass of this product contains the energy equivalent of
85 million tons of TNT per net ounce of weight.
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166055491.244239.305650@t46g2000cwa.googlegroups.com>
> Well, the consensus is that we just don't.

I meant consensus on what is possible, not on common practice, good
style or esthetics...

> What purpose is it?

I need to paste together (1) a library of functions and (2) a bunch of
global declarations in which I have no control over the variable names
(but I do have control over the declaration format).

If (2) defines globals for things like f or x, I don't want that to
screw up normal code in (1) that happens to use local variables f and
x.

For one reason or another, the global declarations in (2) need to be
symbol-values, not function values.
From: Juho Snellman
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <slrneo23tl.jlo.jsnell@sbz-30.cs.Helsinki.FI>
·········@sneakemail.com <·········@sneakemail.com> wrote:
>> Well, the consensus is that we just don't.
>
> I meant consensus on what is possible, not on common practice, good
> style or esthetics...

The possible, the commonly practiced, and the stylish way of getting
"global lexicals" this is by using symbol macros. This has been
mentioned several times in this thread, including once with example
code in a message that you replied to. Obviously you're finding it to
be an inadequate solution in some way, but I don't think you've
explained why.

-- 
Juho Snellman
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166086951.308261.217550@t46g2000cwa.googlegroups.com>
> The possible, the commonly practiced, and the stylish way of getting
> "global lexicals" this is by using symbol macros. This has been
> mentioned several times in this thread, including once with example
> code in a message that you replied to. Obviously you're finding it to
> be an inadequate solution in some way, but I don't think you've
> explained why.

(1) I haven't gotten around to trying symbol macros, and I don't quite
grok them yet. I'm not sure what the implications in compiled code, or
in multiple-source-file programs would be.

(2) since I've decided I'm fine with non-pervasive globals, something
like (locally (declare (special x)) (setq x 10)) or (setf (symbol-value
x) 10) seems simpler, if only it worked (note that SBCL gives no
warning for either of these 2, unlike for a naked setq)

(3) it seems strange that "normal code" inside a defun is at risk of
having its meaning changed by a global definition. There has to be a
way to create global definitions that don't affect normal
lexical-scoped code. If there isn't, I want to know it for sure.

'(|Dan|)
From: Thomas A. Russ
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <ymik60ujgr4.fsf@sevak.isi.edu>
·········@sneakemail.com writes:

> > Well, the consensus is that we just don't.
> 
> I meant consensus on what is possible, not on common practice, good
> style or esthetics...

I don't think you'll find this consensus, since it doesn't really
exist.  (Although I guess symbol macros might qualify.  In all my lisp
years, I've never used them.)

> > What purpose is it?
> 
> I need to paste together (1) a library of functions and (2) a bunch of
> global declarations in which I have no control over the variable names
> (but I do have control over the declaration format).
> 
> If (2) defines globals for things like f or x, I don't want that to
> screw up normal code in (1) that happens to use local variables f and
> x.

Ah.  You should have told us sooner.
In that case, it seems like the proper solution is to use packages to
isolate the variable names over which you have no control from the code
you write that uses these potentially common names.

As in so many things, if we know what you are really trying to do, there
is often a much easier solution than trying to change the fundamental
semantics of the language.

> For one reason or another, the global declarations in (2) need to be
> symbol-values, not function values.

OK, good.  So just make them dynamic global variables in a package of
your choosing.

Write your code in another package and just refer to the globals with a
package prefix.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166144260.728491.103540@t46g2000cwa.googlegroups.com>
> Ah.  You should have told us sooner.
> In that case, it seems like the proper solution is to use packages to
> isolate the variable names over which you have no control from the code
> you write that uses these potentially common names.

I was afraid this was going to be proposed :) There's one more wrinkle:
there part that I have no control keeps expanding (i.e. more code is
generated into it), and includes not only globals, but also normal
(defun)-style code. And, again, I do not want a silly global x screwing
up normal lexically-scoped code inside a (defun),

And, besides, I'd like to know the final answer to this puzzle that
I've started :)
From: Thomas A. Russ
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <ymifybgkea6.fsf@sevak.isi.edu>
·········@sneakemail.com writes:

> > Ah.  You should have told us sooner.
> > In that case, it seems like the proper solution is to use packages to
> > isolate the variable names over which you have no control from the code
> > you write that uses these potentially common names.
> 
> I was afraid this was going to be proposed :) There's one more wrinkle:
> there part that I have no control keeps expanding (i.e. more code is
> generated into it), and includes not only globals, but also normal
> (defun)-style code. And, again, I do not want a silly global x screwing
> up normal lexically-scoped code inside a (defun),

I guess we're running out of ideas.  Perhaps your plight could be
featured in "Dilbert"?

It seems that you are in the unenviable position of trying to get a
collection of broken code, over which you have no control, to work
together in a single system.

This seems to transcend a technical solution, since the fundamental
issue is more one of process and control than a particular technical
issue.  You really need to try to get the code generation to really put
the global and lexical variables into separate namespaces.  The standard
convention of using "*" to surround the names is one way of doing just
that.

But more fundamentally you are still screwed.  I mean what happens when
you get some code like this:

  (defun foo ()
      x)

  (defun bar ()
      x)

where the intent of foo and bar are each to refer to their OWN global
variable?  Then when you end up calling this in an evironment where X is
bound, it affects both equally, even if that isn't intended.


> And, besides, I'd like to know the final answer to this puzzle that
> I've started :)

I can relate to and understand this.
I think you are stuck with symbol macros, but that may not work given
your constraints.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ·········@sneakemail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166271133.754336.157210@16g2000cwy.googlegroups.com>
> It seems that you are in the unenviable position of trying to get a
> collection of broken code, over which you have no control, to work
> together in a single system.

Thanks for sympathizing... But it didn't have to be this bad.

The code is basically translated from a domain-specific language. Lisp
is used as a glue to other resources. That DSL language uses its own
globals in a consistent way (but I certainly don't want to impose
naming or stylistic conventions on the end-users). It has clean lexical
scope. The only translation problem is caused by the pervasiveness of
Lisp's defvar.

Maybe symbol macros would work; I need to test them. I'm not sure if
the "backing variable" stays the same across multiple source files --
that's one of my concerns.

> the global and lexical variables into separate namespaces.  The standard
> convention of using "*" to surround the names is one way of doing just
> that.

I can't really, since the DSL assumes it can use both a global f and a
local lexical f without them interfering with each other -- which, to
me anyway, makes more sense than the super-complex Common Lisp
behavior.

> But more fundamentally you are still screwed.  I mean what happens when
> you get some code like this:
>
>   (defun foo ()
>       x)
>
>   (defun bar ()
>       x)

No, not if the original DSL code was correct.

> I can relate to and understand this.
> I think you are stuck with symbol macros, but that may not work given
> your constraints.

Will report.
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <87lkl7j025.fsf@thalassa.informatimago.com>
·········@sneakemail.com writes:

>> It seems that you are in the unenviable position of trying to get a
>> collection of broken code, over which you have no control, to work
>> together in a single system.
>
> Thanks for sympathizing... But it didn't have to be this bad.
>
> The code is basically translated from a domain-specific language. Lisp
> is used as a glue to other resources. That DSL language uses its own
> globals in a consistent way (but I certainly don't want to impose
> naming or stylistic conventions on the end-users). It has clean lexical
> scope. The only translation problem is caused by the pervasiveness of
> Lisp's defvar.

Perhaps you could modify the translation process to add stars to the
name of the globals?


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

PUBLIC NOTICE AS REQUIRED BY LAW: Any use of this product, in any
manner whatsoever, will increase the amount of disorder in the
universe. Although no liability is implied herein, the consumer is
warned that this process will ultimately lead to the heat death of
the universe.
From: ·······@gmail.com
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166324298.686268.66130@l12g2000cwl.googlegroups.com>
> Perhaps you could modify the translation process to add stars to the
> name of the globals?

I don't think that works, unless I start tracking scopes and
environments... Suppose the DSL code is (in an equivalent Lisp-like
syntax for readability)

(setq x 10)

(setq f
  (lambda (y) (let ((x (+ y 1))) (* x 2)))

In (* x 2), how would I know if x is the global x (and thus needs
stars), or the local one?

Other than the issue of defvar pervasiveness, the translation would be
mechanical. I am reluctant to start tracking environments/scopes. It
seems that I am so close...

Of course, I could use Scheme instead of Lisp, and the pervasiveness
issue would disappear; but since Lisp is used as the glue to an
existing body of code and libraries, that wouldn't be practical either.
From: jayessay
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <m3slfhdqok.fsf@rigel.goldenthreadtech.com>
·········@sneakemail.com writes:

> > (locally (declare (special fff))
> >     ;; here, fff is a dynamic variable.
> >     (setq fff 10))

Have you read the description of locally:

http://www.lispworks.com/documentation/HyperSpec/Body/s_locall.htm

In particular, the Notes?  There you will see that what you have
written is defined to be the same as:

(setq fff 10)


> It seems that dynamic variables spring into existence when assigned to;

No, a top level (setq fff 10) without prior declaration of FFF (via
def*) has "undefined consequences", i.e., implementation defined
behavior.  For this example, most (all??) extent implementations treat
this as an implicit (defparameter fff 10).  That, of course, means
that FFF is declared to be special.  If you _compile_ such and
expression, you will (typically) get warnings about FFF being treated
specially.


> (defun tst () (locally (declare (special fff)) (setq fff 10)))
> (tst)
> fff
> ;; => 10

I'd say this is a "pathological use case", which maybe should be
caught at runtime if you haven't (def* fff ...) before running tst.
Why?  Well, because as it sits, you are telling the compiler that
despite fff not being defined anywhere, that it is to be treated as a
special (dynamic) variable and so at compile time, the compiler
shouldn't issue an error/warning and should generate code to update a
dynamic variable called fff.  However, at runtime, if you haven't
(def* fff ...) yet, I could see this as failing with "undefined
variable" as much as "just working" via the implicit (defparameter fff
10) that you might expect from the setq.  Certain implementations may
indeed blowup here with errors.


> Reading the PDF, I took this behavior for granted

Read the specification...


> but after this discussion, I'm confused.

Again, read LOCALLY in the spec.  That plus the above should clarify
things.


> Once more, Common Lisp has ambiguities and complexities even in some
> of its very basic building blocks.

As far as I can tell, there are no ambiguities here - you are simply
trying to depend on unspecified behavior.


> This is ridiculous. Even more ridiculous is that people seem to put
> up with it with a wide grin. Anyway...

<sigh>...  You should understand this stuff first before going off on
what is or isn't "ridiculous".  It will help your credibility...


> Is there at least any consensus on how to create a non-pervasive
> dynamic global?

Yes - as you've been told a couple of times: symbol macros.  It is
unclear why you refuse to accept this even though it is exactly what
you've asked for.


> confirm that (locally (declare...) (setq ...) is correct?

It's not - per the spec.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Marcus Breiing
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <elsiut$cjq$1@chessie.cirr.com>
jayessay <······@foo.com> writes:

> ·········@sneakemail.com writes:
> 
> > > (locally (declare (special fff))
> > >     ;; here, fff is a dynamic variable.
> > >     (setq fff 10))

> ... you will see that what you have
> written is defined to be the same as:
> 
> (setq fff 10)

According to spec, declarations refer to bindings (not symbols). If no
binding (in the global environment) for FFF has been established
before, one may therefore ask what binding is referred by

  (locally (declare (special fff)) ...)

One possible anwer: none. It is an error.

Another possible answer: Since a declaration _is_ specified to refer
to a binding, it may _cause_ fff to be bound.

Interestingly, CMUCL manages to agree to _both_ of these views,
depending on the kind of declaration.

Assume that FFF is unbound. Then, in CMUCL,

  (locally (declare) (setf fff 99))

warns about the unbound variable, while

  (locally (declare (special fff)) (setf fff 99))

doesn't: The declaration actually seems to create a binding.

However, while

  (locally (declare (special fff))),

consistent with the above, doesn't warn about anything,

  (locally (declare (integer fff)))

again warns about the unbound variable.

Thus SPECIAL declarations of a previously unbound variables "default"
the binding in CMUCL, while TYPE declarations don't.

-- 
Marcus Breiing
(Cologne, Germany)
From: jayessay
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <m3fybgeo39.fsf@rigel.goldenthreadtech.com>
Marcus Breiing <······@2006w49.mail.breiing.com> writes:

> jayessay <······@foo.com> writes:
> 
> > ·········@sneakemail.com writes:
> > 
> > > > (locally (declare (special fff))
> > > >     ;; here, fff is a dynamic variable.
> > > >     (setq fff 10))
> 
> > ... you will see that what you have
> > written is defined to be the same as:
> > 
> > (setq fff 10)
> 
> According to spec, declarations refer to bindings (not symbols). If no
> binding (in the global environment) for FFF has been established
> before, one may therefore ask what binding is referred by
> 
>   (locally (declare (special fff)) ...)
> 
> One possible anwer: none. It is an error.
> 
> Another possible answer: Since a declaration _is_ specified to refer
> to a binding, it may _cause_ fff to be bound.

Maybe, but that isn't specified anywhere.  As you say, there are
various possibilities, and what is more, the specification indicates
this by saying this sort of thing has "undefined consequences".  To
remove the "undefined consequences" at the top level you need to
declaim it (typically, and idiomatically, via def*).  That's it.


> Interestingly, CMUCL manages to agree to _both_ of these views,
> depending on the kind of declaration.
> 
> Assume that FFF is unbound. Then, in CMUCL,
> 
>   (locally (declare) (setf fff 99))
> 
> warns about the unbound variable, while
> 
>   (locally (declare (special fff)) (setf fff 99))
> 
> doesn't: The declaration actually seems to create a binding.

Again, using locally here at the top level is defined to be the same
as just the body: (setf fff 99), whatever CMUCL is doing after that is
obviously implementation defined behavior that has nothing to do with
the spec.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Marcus Breiing
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <eltjrf$gh4$1@chessie.cirr.com>
jayessay <······@foo.com> writes:

> To remove the "undefined consequences" at the top level you need to
> declaim it (typically, and idiomatically, via def*). That's it.

[Looking at the spec once more...]

Before this discussion started, I'd have thought as well that 

  (locally (declare (special *x*)) (setq *x* 1))

would necessarily be equivalent to

  (setq *x* 1). 

I'm not so sure anymore.

The problem is that I can't find the language in the spec that clearly
makes SPECIAL proclamations _different_ from free declarations (eg via
LOCALLY) wrt whether they cause the binding to "exist" or not. From
the description of SPECIAL:

  special declarations can be either bound declarations, affecting
  both a binding and references, or free declarations, affecting only
  references, depending on whether the declaration is attached to a
  variable binding.

  When used in a proclamation, a special declaration specifier applies
  to all bindings as well as to all references of the mentioned
  variables.

The spec on PROCLAIM says it establishes declarations (not bindings).
Well, so does LOCALLY, only locally.

Given this lack of differentiation, why *should* the SETQ references
in the following behave differently?

(locally (declare (special *x*)) (setq *x* 1))

(progn (proclaim '(special *x*)) (setq *x* 1))

-- 
Marcus Breiing
(Cologne, Germany)
From: Pascal Costanza
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <4uf5klF17p05lU1@mid.individual.net>
Marcus Breiing wrote:
> jayessay <······@foo.com> writes:
> 
>> To remove the "undefined consequences" at the top level you need to
>> declaim it (typically, and idiomatically, via def*). That's it.
> 
> [Looking at the spec once more...]
> 
> Before this discussion started, I'd have thought as well that 
> 
>   (locally (declare (special *x*)) (setq *x* 1))
> 
> would necessarily be equivalent to
> 
>   (setq *x* 1). 
> 
> I'm not so sure anymore.

My mental model is that

(locally (declare (special *x*)) (setq *x* 1))

is equivalent to:

(setf (symbol-value '*x*) 1)

In other words, a local special declaration "opens up" the symbol values 
of the respective symbols.

> The spec on PROCLAIM says it establishes declarations (not bindings).
> Well, so does LOCALLY, only locally.
> 
> Given this lack of differentiation, why *should* the SETQ references
> in the following behave differently?
> 
> (locally (declare (special *x*)) (setq *x* 1))
> 
> (progn (proclaim '(special *x*)) (setq *x* 1))

Proclaim doesn't have compile-time effects. The former local declaration 
tells the compiler something about the variable *x*. The latter tells 
the runtime system that from the point of execution of the proclaim form 
on, all further occurrences of *x* should be treated as specials. By 
that time, the subsequent reference to *x* has already been treated as a 
lexical variable by the compiler.

In other words, proclaim is the functional substrate of declaim and 
declare, and should probably only be used when doing meta-level stuff.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Marcus Breiing
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <elu1af$iek$1@chessie.cirr.com>
Pascal Costanza <··@p-cos.net> writes:

> > (locally (declare (special *x*)) (setq *x* 1))
> > (progn (proclaim '(special *x*)) (setq *x* 1))

> Proclaim doesn't have compile-time effects. 

Indeed - that's a bug in my question :-)

Hopefully 

  (locally (declare (special *x*)) (setq *x* 1))
  (progn (declaim (special *x*)) (setq *x* 1))

fixes it... the meat of the question was whether the effect of the
SPECIAL declaration on this specific reference to the (previously
unbound) *x* is different depending on whether we have a local (free)
or global SPECIAL declaration. The poster I responded to seemed to
think so (one being undefined, the other defined behavior), and so did
I - but I subsequently noticed that I can't find justification for
making this distinction.

-- 
Marcus Breiing
(Cologne, Germany)
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <87lkl9l4q1.fsf@thalassa.informatimago.com>
Marcus Breiing <······@2006w49.mail.breiing.com> writes:

> Pascal Costanza <··@p-cos.net> writes:
>
>> > (locally (declare (special *x*)) (setq *x* 1))
>> > (progn (proclaim '(special *x*)) (setq *x* 1))
>
>> Proclaim doesn't have compile-time effects. 
>
> Indeed - that's a bug in my question :-)
>
> Hopefully 
>
>   (locally (declare (special *x*)) (setq *x* 1))
>   (progn (declaim (special *x*)) (setq *x* 1))

As a top level form, this PROGN is equivalent to:

(declaim (special *x*))
(setq *x* 1)

which is equivalent to:

(defparameter *x* 1)


> fixes it... the meat of the question was whether the effect of the
> SPECIAL declaration on this specific reference to the (previously
> unbound) *x* is different depending on whether we have a local (free)
> or global SPECIAL declaration. The poster I responded to seemed to
> think so (one being undefined, the other defined behavior), and so did
> I - but I subsequently noticed that I can't find justification for
> making this distinction.
>
> -- 
> Marcus Breiing
> (Cologne, Germany)

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d? s++:++ a+ C+++ UL++++ P--- L+++ E+++ W++ N+++ o-- K- w--- 
O- M++ V PS PE++ Y++ PGP t+ 5+ X++ R !tv b+++ DI++++ D++ 
G e+++ h+ r-- z? 
------END GEEK CODE BLOCK------
From: Thomas A. Russ
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <ymiodq6jh3o.fsf@sevak.isi.edu>
·········@sneakemail.com writes:

> Pascal, this is where you were wrong....
> (2) setq defines a global special (not lexical) variable.

This is not correct.

SETQ does NOT define a global special variable.

DEFVAR and DEFPARAMETER do that, as can an appropriate PROCLAIM or
DECLAIM form.  The effects of invoking SETQ on a variable that has not
previously been declared to be special using one of the above methods is
undefined behavior in the ANSI standard.  Now, it just so happens that
because of long tradition (and thus user expectations), all
implementations that I know of do, in fact, treat globally free
variables as special variables.

Now whether this is done just as a local interpretation or in a globally
pervasive fashion happens to be implementation dependent.  Many lisps
will treat

  (defun (foo)
     (print bar))

as being

  (defun (foo)
     (declare (special bar))
     (print bar))

but CMUCL, IIRC choose instead to treat this as:

  (declaim (special bar))
  (defun (foo)
     (print bar))

Both behaviors are conforming, insofar as there is no particular
behavior mandated by the standard for handling this case.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: rydis (Martin Rydstr|m) @CD.Chalmers.SE
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <w4cd56llzlg.fsf@rackham.cd.chalmers.se>
···@sevak.isi.edu (Thomas A. Russ) writes:
> Now whether this is done just as a local interpretation or in a globally
> pervasive fashion happens to be implementation dependent.  Many lisps
> will treat
> 
>   (defun (foo)
>      (print bar))
> 
> as being
> 
>   (defun (foo)
>      (declare (special bar))
>      (print bar))
> 
> but CMUCL, IIRC choose instead to treat this as:
> 
>   (declaim (special bar))
>   (defun (foo)
>      (print bar))
> 
> Both behaviors are conforming, insofar as there is no particular
> behavior mandated by the standard for handling this case.

The CMUCL behaviour is settable:
---
* (describe 'ext:*top-level-auto-declare*)

*TOP-LEVEL-AUTO-DECLARE* is an external symbol in the EXTENSIONS  package.
It is a special variable; its value is :WARN.
   WARN is an external symbol in the KEYWORD package.
   It is a constant; its value is :WARN.
Special documentation:
  This variable controls whether assignments to unknown variables at  top-level
   (or in any other call to EVAL of SETQ) will implicitly declare the variable
   SPECIAL.  These values are meaningful:
     :WARN  -- Print a warning, but declare the variable special (the default.)
      T     -- Quietly declare the variable special.
      NIL   -- Never declare the variable, giving warnings on each use.
It is defined in:
target:code/eval.lisp
---

(Setting it to NIL would give the behaviour of "many lisps", above, IIUC.)

Regards,

',mr

-- 
rydis (Martin Rydstr�m) @CD.Chalmers.SE             http://www.rydis.se

[Emacs] is written in Lisp, which is the only computer language that is
beautiful.  -- Neal Stephenson, _In the Beginning was the Command Line_
From: Juho Snellman
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <slrneo0kun.cf2.jsnell@sbz-30.cs.Helsinki.FI>
Alex Mizrahi <········@users.sourceforge.net> wrote:
> (message (Hello 'Pascal)
> (you :wrote  :on '(Wed, 13 Dec 2006 14:15:50 +0100))
> (
>
>  PB> Well, that's the point: there is no _standard_ way to define a global
>  PB> non-dynamic variable.
>
>  PB> So, it seems that both sbcl and clisp allow defining global "lexical"
>  PB> variables with SETF/SETQ.  But this is no standard Common Lisp.
>
> i wonder what's wrong with this:
>
> CG-USER(1): (setf (symbol-value 'varr) 10)
> 10
> CG-USER(2): (funcall (let ((varr 11)) (lambda () varr)))
> 11
> CG-USER(3): varr
> 10
>
> ain't that "global non-dynamic variable"?

No, it is undefined behaviour. The standard specifies (in 3.1.2.1.1)
three kinds of variables, none of which VARR fits. The standard also
doesn't specify what should be done for non-variables that are used
syntactically like variables.

It happens that all implementations I know of have chosen the same
behaviour for this, and interpret VARR as referring to the value slot
of the symbol (though sometimes with warnings of an undefined variable
being used). Thus the following code will print 11, even though FOO
hasn't been declared special either globally or in the lexical scope
of BAR.

    (setf (symbol-value 'foo) 10)

    (defun bar ()
      foo)
  
    (let ((foo 11))
      (declare (special foo))
      (print (bar)))

So really, if you want "global lexicals", you need to use
symbol-macros.

-- 
Juho Snellman
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <87ac1rpmxm.fsf@thalassa.informatimago.com>
Juho Snellman <······@iki.fi> writes:

> Alex Mizrahi <········@users.sourceforge.net> wrote:
>> (message (Hello 'Pascal)
>> (you :wrote  :on '(Wed, 13 Dec 2006 14:15:50 +0100))
>> (
>>
>>  PB> Well, that's the point: there is no _standard_ way to define a global
>>  PB> non-dynamic variable.
>>
>>  PB> So, it seems that both sbcl and clisp allow defining global "lexical"
>>  PB> variables with SETF/SETQ.  But this is no standard Common Lisp.
>>
>> i wonder what's wrong with this:
>>
>> CG-USER(1): (setf (symbol-value 'varr) 10)
>> 10
>> CG-USER(2): (funcall (let ((varr 11)) (lambda () varr)))
>> 11
>> CG-USER(3): varr
>> 10
>>
>> ain't that "global non-dynamic variable"?
>
> No, it is undefined behaviour. The standard specifies (in 3.1.2.1.1)
> three kinds of variables, none of which VARR fits. The standard also
> doesn't specify what should be done for non-variables that are used
> syntactically like variables.
>
> It happens that all implementations I know of have chosen the same
> behaviour for this, and interpret VARR as referring to the value slot
> of the symbol (though sometimes with warnings of an undefined variable
> being used). Thus the following code will print 11, even though FOO
> hasn't been declared special either globally or in the lexical scope
> of BAR.
>
>     (setf (symbol-value 'foo) 10)
>
>     (defun bar ()
>       foo)
>   
>     (let ((foo 11))
>       (declare (special foo))
>       (print (bar)))
>
> So really, if you want "global lexicals", you need to use
> symbol-macros.

Well, right, but (setf (symbol-value 'sym) val) and  (symbol-value 'sym) 
seem to be defined independently of the different kind of variable.

So you're right that using sym to access (symbol-value 'sym) in the
case of a non dynamic variable is not specified, but we can use
symbol-value.


(setf (symbol-value 'varr) 10)

Inside a lexical scope, we can clearly access either the lexical
variable, or the symbol value:

(funcall (let ((varr 11)) (lambda () (symbol-value 'varr))))
--> 10
(funcall (let ((varr 11)) (lambda () varr)))
--> 11

In the global scope, we can only legally access the symbol value:

(symbol-value 'varr)
--> 10



varr ; is undefined apparently.

But:

(boundp 'varr) 
--> T



By the way, I don't find a clear specification that SYMBOL-VALUE
should access the value of dynamic variables...  There's some weak
correlation of the two thru boundp, but that's all I can find.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

PLEASE NOTE: Some quantum physics theories suggest that when the
consumer is not directly observing this product, it may cease to
exist or will exist only in a vague and undetermined state.
From: Juho Snellman
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <slrneo0oql.drl.jsnell@sbz-30.cs.Helsinki.FI>
Pascal Bourguignon <···@informatimago.com> wrote:
> Well, right, but (setf (symbol-value 'sym) val) and  (symbol-value 'sym) 
> seem to be defined independently of the different kind of variable.
>
> So you're right that using sym to access (symbol-value 'sym) in the
> case of a non dynamic variable is not specified, but we can use
> symbol-value.

But why in the world would anyone do that, if the goal is to get
"global lexicals"? There's a good and simple way to accomplish that,
by using symbol-macros.

> By the way, I don't find a clear specification that SYMBOL-VALUE
> should access the value of dynamic variables...  There's some weak
> correlation of the two thru boundp, but that's all I can find.

See the description of the SYMBOL class:

  Value

    If a symbol has a value attribute, it is said to be bound, and
    that fact can be detected by the function boundp. The object
    contained in the value cell of a bound symbol is the value of the
    global variable named by that symbol, and can be accessed by the
    function symbol-value. A symbol can be made to be unbound by the
    function makunbound.
    
  [...]

  Operations on a symbol's value cell and function cell are sometimes
  described in terms of their effect on the symbol itself, but the
  user should keep in mind that there is an intimate relationship
  between the contents of those cells and the global variable or
  global function definition, respectively.

-- 
Juho Snellman
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <871wn3pllk.fsf@thalassa.informatimago.com>
Juho Snellman <······@iki.fi> writes:

> Pascal Bourguignon <···@informatimago.com> wrote:
>> Well, right, but (setf (symbol-value 'sym) val) and  (symbol-value 'sym) 
>> seem to be defined independently of the different kind of variable.
>>
>> So you're right that using sym to access (symbol-value 'sym) in the
>> case of a non dynamic variable is not specified, but we can use
>> symbol-value.
>
> But why in the world would anyone do that, if the goal is to get
> "global lexicals"? There's a good and simple way to accomplish that,
> by using symbol-macros.
>
>> By the way, I don't find a clear specification that SYMBOL-VALUE
>> should access the value of dynamic variables...  There's some weak
>> correlation of the two thru boundp, but that's all I can find.
>
> See the description of the SYMBOL class:
>
>   Value
>
>     If a symbol has a value attribute, it is said to be bound, and
>     that fact can be detected by the function boundp. The object
>     contained in the value cell of a bound symbol is the value of the
>     global variable named by that symbol, and can be accessed by the
>     function symbol-value. A symbol can be made to be unbound by the
>     function makunbound.

Ah right. And global variables are either dynamic variables or
constant variables.
     
>   [...]
>
>   Operations on a symbol's value cell and function cell are sometimes
>   described in terms of their effect on the symbol itself, but the
>   user should keep in mind that there is an intimate relationship
>   between the contents of those cells and the global variable or
>   global function definition, respectively.

Ok so (setf (symbol-value 'sym) val) really binds a dynamic variable,
but it doesn't declare it special in the global or any environment.

So evaluating sym in the global environment accesses the dynamic
variable because it is in the global environment, and
(funcall (let ((sym 'lex-val)) (lambda () sym)))
returns lex-val since the lambda use the lexical binding of sym.

And similarly for the (locally (declare (special sym) (setf sym val))).


And then, SET and SETQ don't  do the same thing, but archieve the same
effect.
SET is equivalent to (setf (symbol-value sym) val)
while SETQ can magically access the dynamic variable in the global
environment even when it's not declared special!

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"What is this talk of "release"?  Klingons do not make software
"releases".  Our software "escapes" leaving a bloody trail of
designers and quality assurance people in its wake."
From: Alex Mizrahi
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <45806752$0$49201$14726298@news.sunsite.dk>
(message (Hello 'Juho)
(you :wrote  :on '(13 Dec 2006 19:26:15 GMT))
(

 JS> No, it is undefined behaviour. The standard specifies (in 3.1.2.1.1)
 JS> three kinds of variables, none of which VARR fits. The standard also
 JS> doesn't specify what should be done for non-variables that are used
 JS> syntactically like variables.

no, it IS a variable.

the standard defines what unbound variable is, but is it dynamic, lexical or 
constant variable unbound? :)

looks like (setf (symbol-value 'varr) 1) creates a global binding, so it's 
not a unbound variable.

i think you can assume that it's a dynamic variable when referenced in 
top-level, since description of what dynamic varibles is is very vague :)

 JS> It happens that all implementations I know of have chosen the same
 JS> behaviour for this, and interpret VARR as referring to the value slot
 JS> of the symbol (though sometimes with warnings of an undefined variable
 JS> being used).

which ones produce warning? i've checked acl, lispworks, clisp and sbcl --  
no one produces warnings.

i'm not sure, but i think unless we assume that this interpretation of 
standard is correct, we can find a contradiction in standard -- that is much 
worse than simply 'undefined behaviour'.

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"People who lust for the Feel of keys on their fingertips (c) Inity") 
From: Juho Snellman
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <slrneo0rio.e6r.jsnell@sbz-30.cs.Helsinki.FI>
Alex Mizrahi <········@users.sourceforge.net> wrote:
> (message (Hello 'Juho)
> (you :wrote  :on '(13 Dec 2006 19:26:15 GMT))
> (
>
>  JS> No, it is undefined behaviour. The standard specifies (in 3.1.2.1.1)
>  JS> three kinds of variables, none of which VARR fits. The standard also
>  JS> doesn't specify what should be done for non-variables that are used
>  JS> syntactically like variables.
>
> no, it IS a variable.

It's not a lexical variable (clhs 3.1.2.1.1.1): 

   A lexical variable is a variable that can be referenced only
   within the lexical scope of the form that establishes that variable.
   [ Not true in this case; there is no form in the lexical scope
     of the toplevel VARR establishing such a binding ]

It's not a special variable (clhs 3.1.2.1.1.2):

   A variable is a dynamic variable if one of the following conditions
   hold [sic]:

   * It is locally declared or globally proclaimed special. 
     [ Not true in this case]   
   * It occurs textually within a form that creates a dynamic
     binding for a variable of the same name, and the binding is
     not shadowed[2] by a form that creates a lexical binding of
     the same variable name.
     [ Not true in this case]

It's not a constant variable (clhs 3.1.2.1.1.3):
   
   Obviously.

> the standard defines what unbound variable is, but is it dynamic, lexical or 
> constant variable unbound? :)

Sorry, I don't understand what you mean here.

> looks like (setf (symbol-value 'varr) 1) creates a global binding, so it's 
> not a unbound variable.

It sets the value slot of the variable. No more, no less. The presence
of data in the symbol-value slot doesn't determine whether a symbol
names a variable or not.

>  JS> It happens that all implementations I know of have chosen the same
>  JS> behaviour for this, and interpret VARR as referring to the value slot
>  JS> of the symbol (though sometimes with warnings of an undefined variable
>  JS> being used).
>
> which ones produce warning? i've checked acl, lispworks, clisp and sbcl --  
> no one produces warnings.

My memory was playing tricks on me. In fact, all implementations that
I tested (acl, clisp, cmucl, ecl, gcl, and sbcl) will warn for
accessing undefined variables, rather than only some of them warning:

  (setf (symbol-value 'foo) 1)
  (compile nil '(lambda () foo))

> i'm not sure, but i think unless we assume that this interpretation of 
> standard is correct, we can find a contradiction in standard -- that is much 
> worse than simply 'undefined behaviour'.

That argument would be more credible if you pointed out the
contradiction, rather than suggesting that one might possibly exist :-)

-- 
Juho Snellman
From: Alex Mizrahi
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <458077a9$0$49202$14726298@news.sunsite.dk>
(message (Hello 'Juho)
(you :wrote  :on '(13 Dec 2006 21:19:20 GMT))
(

 ??>> no, it IS a variable.

"If a form is a symbol that is not a symbol macro, then it is the name of a 
variable,"

 ??>> the standard defines what unbound variable is, but is it dynamic,
 ??>> lexical or constant variable unbound? :)

 JS> Sorry, I don't understand what you mean here.

"An error of type unbound-variable should be signaled if an unbound variable 
is referenced."

if we use your classification, we find that unbound variable is 
non-variable, that is non-sense. thus, we have to admit that there are other 
kinds of variable except lexical, dynamic and constant -- at least there is 
class of unbound variables.

 ??>> looks like (setf (symbol-value 'varr) 1) creates a global binding, so
 ??>> it's not a unbound variable.

 JS> It sets the value slot of the variable. No more, no less. The presence
 JS> of data in the symbol-value slot doesn't determine whether a symbol
 JS> names a variable or not.

there is no such thing as "symbol names a variable or not" -- ALL symbols 
are variables as EXPLICITLY is said in specification (see above). variable 
can be bound or unbound -- that is the question.

we have to determine, if setting symbol-value makes variable bound or not.
although there is no direct definition, it's implied in some places, for 
example, what did you quote:

"but the user should keep in mind that there is an intimate relationship
  between the contents of those cells and the global variable or
  global function definition, respectively."

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"People who lust for the Feel of keys on their fingertips (c) Inity") 
From: Mattias Nilsson
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <1166063000.501295.65600@l12g2000cwl.googlegroups.com>
>  ??>> no, it IS a variable.
>
> "If a form is a symbol that is not a symbol macro, then it is the name of a
> variable,"
>
>  ??>> the standard defines what unbound variable is, but is it dynamic,
>  ??>> lexical or constant variable unbound? :)
>
>  JS> Sorry, I don't understand what you mean here.
>
> "An error of type unbound-variable should be signaled if an unbound variable
> is referenced."
>
> if we use your classification, we find that unbound variable is
> non-variable, that is non-sense. thus, we have to admit that there are other
> kinds of variable except lexical, dynamic and constant -- at least there is
> class of unbound variables.
>
>  ??>> looks like (setf (symbol-value 'varr) 1) creates a global binding, so
>  ??>> it's not a unbound variable.
>
>  JS> It sets the value slot of the variable. No more, no less. The presence
>  JS> of data in the symbol-value slot doesn't determine whether a symbol
>  JS> names a variable or not.
>
> there is no such thing as "symbol names a variable or not" -- ALL symbols
> are variables as EXPLICITLY is said in specification (see above). variable
> can be bound or unbound -- that is the question.
>
> we have to determine, if setting symbol-value makes variable bound or not.
> although there is no direct definition, it's implied in some places, for
> example, what did you quote:
>
> "but the user should keep in mind that there is an intimate relationship
>   between the contents of those cells and the global variable or
>   global function definition, respectively."

It's kind of funny to see how this thread mirrors the biggest problem
I've had
while trying to learn CL over the last year or so. And I just thought I
was
slow. :) (Well, of course, I might still be...)

I think I mainly agree with Juho on this one. In addition to the quote
about
value cell <-> global variable above, looking up "value cell" in the
CLHS
glossary tells us:

"value cell n. Trad. (of a symbol) The place which holds the value, if
any, of
 the dynamic variable named by that symbol, and which is accessed by
 symbol-value. See cell."

In other words: If the symbol names a dynamic (special) variable, its
value can
be found in the value cell of the symbol. However, just because a
symbol's
value cell holds a value, it doesn't follow that the symbol names a
variable.

What this means w.r.t. the quote about symbols as forms, I'm not sure,
but I
guess that implementations just skip a check of "specialness", and
deliver the
value from the value cell, no questions asked.

Mattias
From: Juho Snellman
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <slrneo23oe.jlo.jsnell@sbz-30.cs.Helsinki.FI>
Alex Mizrahi <········@users.sourceforge.net> wrote:
>  ??>> the standard defines what unbound variable is, but is it dynamic,
>  ??>> lexical or constant variable unbound? :)
>
>  JS> Sorry, I don't understand what you mean here.
>
> "An error of type unbound-variable should be signaled if an unbound variable 
> is referenced."
>
> if we use your classification, we find that unbound variable is 
> non-variable, that is non-sense. thus, we have to admit that there are other 
> kinds of variable except lexical, dynamic and constant -- at least there is 
> class of unbound variables.

An unbound variable is (according to the glossary), something that
syntactically looks like a (dynamic) variable, but which has no
binding. If a variable with that name isn't bound in the lexical scope
and hasn't been declared as special, it's not a syntactically valid
variable.

But by all means, feel free to assume that referring to an undefined
variable is ok. I'm sure the people responsible putting in those
"undefined variable" compiler warnings into all Lisp implementations
were just ignorant, and didn't understand that this was a completely
valid practice... :-)

-- 
Juho Snellman
From: Alex Mizrahi
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <458078ff$0$49197$14726298@news.sunsite.dk>
(message (Hello 'Juho)
(you :wrote  :on '(13 Dec 2006 21:19:20 GMT))
(

 JS> It's not a special variable (clhs 3.1.2.1.1.2):

 JS>    A variable is a dynamic variable if one of the following conditions
 JS>    hold [sic]:

 JS>    * It is locally declared or globally proclaimed special.
 JS>      [ Not true in this case]

note that this does not say that variable becomes non-dynamic when you're 
outside of "locally" declaration. moreover:

"A dynamic variable can be referenced outside the dynamic extent of a form 
that binds it. Such a variable is sometimes called a ``global variable'' but 
is still in all respects just a dynamic variable whose binding happens to 
exist in the global environment rather than in some dynamic environment."

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"People who lust for the Feel of keys on their fingertips (c) Inity") 
From: Pascal Bourguignon
Subject: Re: lambda-returning defmacro, capture
Date: 
Message-ID: <87ejr3pofb.fsf@thalassa.informatimago.com>
"Alex Mizrahi" <········@users.sourceforge.net> writes:

> (message (Hello 'Pascal)
> (you :wrote  :on '(Wed, 13 Dec 2006 14:15:50 +0100))
> (
>
>  PB> Well, that's the point: there is no _standard_ way to define a global
>  PB> non-dynamic variable.
>
>  PB> So, it seems that both sbcl and clisp allow defining global "lexical"
>  PB> variables with SETF/SETQ.  But this is no standard Common Lisp.
>
> i wonder what's wrong with this:
>
> CG-USER(1): (setf (symbol-value 'varr) 10)
> 10
> CG-USER(2): (funcall (let ((varr 11)) (lambda () varr)))
> 11
> CG-USER(3): varr
> 10
>
> ain't that "global non-dynamic variable"?

Yes, this sounds good.
So there IS a standard way to define a global non-dynamic variable.



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

COMPONENT EQUIVALENCY NOTICE: The subatomic particles (electrons,
protons, etc.) comprising this product are exactly the same in every
measurable respect as those used in the products of other
manufacturers, and no claim to the contrary may legitimately be
expressed or implied.