unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
@ 2017-01-03 14:14 Alan Mackenzie
  2017-01-03 18:35 ` Stefan Monnier
  0 siblings, 1 reply; 23+ messages in thread
From: Alan Mackenzie @ 2017-01-03 14:14 UTC (permalink / raw)
  To: emacs-devel

Hello, Emacs.

I'm in Emacs 25.1.

I want to M-x compile-defun the function `edebug'.  When I attempt this,
I get the "warning" messages:

    Warning: Unused lexical variable `edebug-break'
    Warning: Unused lexical variable `edebug-global-break'
    Warning: Unused lexical variable `edebug-break-condition'
    Warning: Unused lexical variable `edebug-break-data'
    Warning: Unused lexical variable `edebug-breakpoints'

.  These variables are dynamic ones, declared earlier on in the file
like this:

    (defvar edebug-breakpoints)

, i.e. without initialising expressions.  I tried C-x C-e on each such
declaration, then repeating the compile-defun, to no avail.
lexical-binding is set in edebug.el.

Emacs should be able to compile successfully in such circumstances,
surely?.

What am I doing wrong, here?

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-03 14:14 Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical Alan Mackenzie
@ 2017-01-03 18:35 ` Stefan Monnier
  2017-01-03 21:32   ` Alan Mackenzie
  0 siblings, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2017-01-03 18:35 UTC (permalink / raw)
  To: emacs-devel

> I want to M-x compile-defun the function `edebug'.

Looks like `compile-defun` is another function that needs to be changed
to use `eval-sexp-add-defvars`.


        Stefan




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-03 18:35 ` Stefan Monnier
@ 2017-01-03 21:32   ` Alan Mackenzie
  2017-01-03 21:48     ` Stefan Monnier
  0 siblings, 1 reply; 23+ messages in thread
From: Alan Mackenzie @ 2017-01-03 21:32 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan.

On Tue, Jan 03, 2017 at 01:35:19PM -0500, Stefan Monnier wrote:
> > I want to M-x compile-defun the function `edebug'.

> Looks like `compile-defun` is another function that needs to be changed
> to use `eval-sexp-add-defvars`.

It looks like you've already done that, possibly on 2015-10-29.  Looking
at the source (now I know what to look for), eval-sexp-add-defvars is
also in Emacs 25.1's source for compile-defun.  So, something else has
gone wrong.....

I think the something else might be in Fdefvar.  At its outermost level
Fdefvar contains:

###############################################
  (Lisp_Object args)
{
  Lisp_Object sym, tem, tail;

  sym = XCAR (args);
  tail = XCDR (args);

  if (CONSP (tail))
    {
......
      /* Do it before evaluating the initial value, for self-references.  */
      XSYMBOL (sym)->declared_special = 1;
......
    }
###############################################

, so the question becomes why is setting the declared_special flag done
inside the "if (CONSP (tail))" rather than outside?  I.e. why is it only
done when a variable has an initialisation?

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-03 21:32   ` Alan Mackenzie
@ 2017-01-03 21:48     ` Stefan Monnier
  2017-01-04 13:39       ` Alan Mackenzie
  0 siblings, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2017-01-03 21:48 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: emacs-devel

> It looks like you've already done that, possibly on 2015-10-29.  Looking
> at the source (now I know what to look for), eval-sexp-add-defvars is
> also in Emacs 25.1's source for compile-defun.

Oh, indeed.  Not sure why you're seeing what you're seeing, then.
At least on Emacs's master branch I can't seem to reproduce your problem
(don't have a fresh emacs-25 build to try it right now).

> , so the question becomes why is setting the declared_special flag done
> inside the "if (CONSP (tail))" rather than outside?  I.e. why is it only
> done when a variable has an initialisation?

Because this code is only relevant when you evaluate (defvar <foo>),
whereas here we're not evaluating it, we're only processing it for the
byte-compiler.

There's also the important difference that a (defvar <foo>) only
has effect for the code in the same file rather than having a global
effect, so you can do (defvar toto) and then use `toto` as
a dynamically-scoped variable in your file without wreaking havoc in all
other files which happen to also use `toto` as a (lexical) variable.


        Stefan



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-03 21:48     ` Stefan Monnier
@ 2017-01-04 13:39       ` Alan Mackenzie
  2017-01-04 15:23         ` Stefan Monnier
  0 siblings, 1 reply; 23+ messages in thread
From: Alan Mackenzie @ 2017-01-04 13:39 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan.

On Tue, Jan 03, 2017 at 04:48:15PM -0500, Stefan Monnier wrote:
> > It looks like you've already done that, possibly on 2015-10-29.  Looking
> > at the source (now I know what to look for), eval-sexp-add-defvars is
> > also in Emacs 25.1's source for compile-defun.

> Oh, indeed.  Not sure why you're seeing what you're seeing, then.
> At least on Emacs's master branch I can't seem to reproduce your problem
> (don't have a fresh emacs-25 build to try it right now).

For what it's worth, I can't reproduce the problem any more.  I must
have got my Emacs 25.1 into a strange state, somehow.

> > , so the question becomes why is setting the declared_special flag done
> > inside the "if (CONSP (tail))" rather than outside?  I.e. why is it only
> > done when a variable has an initialisation?

> Because this code is only relevant when you evaluate (defvar <foo>),
> whereas here we're not evaluating it, we're only processing it for the
> byte-compiler.

Understood.  Thanks.

> There's also the important difference that a (defvar <foo>) only
> has effect for the code in the same file rather than having a global
> effect, so you can do (defvar toto) and then use `toto` as
> a dynamically-scoped variable in your file without wreaking havoc in all
> other files which happen to also use `toto` as a (lexical) variable.

Ouch!  There seems to be a clash between symbols (which are global,
dynamic) and lexical variables (which are local and "invisible"): the
only way to mark a variable as lexical is at the global level.

However, I'm seeing something else strange (still on 25.1).  I do this:

(i) M-x load-library edebug.
(ii) visit edebug.el.
(iii) instrument `edebug' for edebugging (yes, I know ;-).
(iv) M-: (edebug).
(v) step through the function to just after the let bindings.
(vi) e (special-variable-p 'edebug-breakpoints).

This last returns nil.  This suggests edebug-breakpoints has been bound
as a lexical variable, rather than a dynamic one.  (There is a defvar
for it earlier in the file.)  This is surely not right.

What is going on here?  Is it, perhaps, a bug?

However, edebug.elc still seems to work, though I haven't successfully
mananged to run `edebug' recently.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-04 13:39       ` Alan Mackenzie
@ 2017-01-04 15:23         ` Stefan Monnier
  2017-01-04 20:04           ` Alan Mackenzie
  0 siblings, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2017-01-04 15:23 UTC (permalink / raw)
  To: emacs-devel

> Ouch!  There seems to be a clash between symbols (which are global,
> dynamic) and lexical variables (which are local and "invisible"): the
> only way to mark a variable as lexical is at the global level.

Yes, there are some subtleties there.  The main issue is that every
occurrence of an identifier, whether a binding occurrence or a "use" can
be lexical or dynamic, but we don't want the coders to have to
constantly specify which uses and which bindings are lexical and which
are dynamic.  So we offer ways to "mark" symbols are "this one uses
dynamic scoping".  There are 2 such ways:
- *Evaluation* of (defvar VAR VAL . REST) marks this variable as being
  dynamically scoped in all the code that will be compiled in this session.
- *Compilation* of (defvar VAR . REST) marks this variable as being
  dynamically scoped in the current compilation unit.

> (vi) e (special-variable-p 'edebug-breakpoints).
>
> This last returns nil.  This suggests edebug-breakpoints has been bound
> as a lexical variable, rather than a dynamic one.  (There is a defvar
> for it earlier in the file.)  This is surely not right.

special-variable-p only indicates if (defvar VAR VAL . REST) was evaluated.


        Stefan




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-04 15:23         ` Stefan Monnier
@ 2017-01-04 20:04           ` Alan Mackenzie
  2017-01-04 21:49             ` Stefan Monnier
  2020-02-13 16:42             ` Drew Adams
  0 siblings, 2 replies; 23+ messages in thread
From: Alan Mackenzie @ 2017-01-04 20:04 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan

On Wed, Jan 04, 2017 at 10:23:16AM -0500, Stefan Monnier wrote:
> > Ouch!  There seems to be a clash between symbols (which are global,
> > dynamic) and lexical variables (which are local and "invisible"): the
> > only way to mark a variable as lexical is at the global level.

> Yes, there are some subtleties there.  The main issue is that every
> occurrence of an identifier, whether a binding occurrence or a "use" can
> be lexical or dynamic, but we don't want the coders to have to
> constantly specify which uses and which bindings are lexical and which
> are dynamic.  So we offer ways to "mark" symbols are "this one uses
> dynamic scoping".  There are 2 such ways:
> - *Evaluation* of (defvar VAR VAL . REST) marks this variable as being
>   dynamically scoped in all the code that will be compiled in this session.
> - *Compilation* of (defvar VAR . REST) marks this variable as being
>   dynamically scoped in the current compilation unit.

> > (vi) e (special-variable-p 'edebug-breakpoints).

> > This last returns nil.  This suggests edebug-breakpoints has been bound
> > as a lexical variable, rather than a dynamic one.  (There is a defvar
> > for it earlier in the file.)  This is surely not right.

> special-variable-p only indicates if (defvar VAR VAL . REST) was evaluated.

So it would seem.  There is a bug in the elisp manual, which says that a
variable being declared by defvar will cause special-variable-p to
return t for it.   The doc string looks right, though far from helpful
for anybody who doesn't already know variable binding inside out, and
even a bit cryptic for those who do.

special-variable-p would appear to be a near useless function, since it
doesn't do what it's name says.

"Defining Variables" in the elisp manual states that "(defvar foo)" makes
foo a special variable; yet "(special-variable-p 'foo)" returns nil.  This
has got to be a bug, of some sort.

There appears to be no way of checking whether a variable's binding is
(or will be) lexical.

I can foresee quite a bit of confusion happening over all this, if it
hasn't happened already.

Am I missing something, or is this all really as incoherent as it
appears to me?

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-04 20:04           ` Alan Mackenzie
@ 2017-01-04 21:49             ` Stefan Monnier
  2017-01-04 22:02               ` Alan Mackenzie
  2020-02-13 16:42             ` Drew Adams
  1 sibling, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2017-01-04 21:49 UTC (permalink / raw)
  To: emacs-devel

> special-variable-p would appear to be a near useless function, since it
> doesn't do what it's name says.

It's useful for the compiler, but it's mostly internal, indeed.

> There appears to be no way of checking whether a variable's binding is
> (or will be) lexical.

In which context do you need/want to do that (I ask because how to do
it (and even if it can be done) depends on the details)?


        Stefan




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-04 21:49             ` Stefan Monnier
@ 2017-01-04 22:02               ` Alan Mackenzie
  2017-01-04 22:26                 ` Stefan Monnier
  0 siblings, 1 reply; 23+ messages in thread
From: Alan Mackenzie @ 2017-01-04 22:02 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan.

On Wed, Jan 04, 2017 at 04:49:15PM -0500, Stefan Monnier wrote:
> > special-variable-p would appear to be a near useless function, since it
> > doesn't do what it's name says.

> It's useful for the compiler, but it's mostly internal, indeed.

OK.

> > There appears to be no way of checking whether a variable's binding is
> > (or will be) lexical.

> In which context do you need/want to do that (I ask because how to do
> it (and even if it can be done) depends on the details)?

I honestly don't know.  I presume that there will be code (other than
the byte compiler) which will want to make a distinction.  Maybe there's
not.  After (defvar foo), the byte compiler seems able to handle foo as
a dynamic variable.  I'm still trying to figure out how, given that that
flag denoting a special variable in the struct symbol doesn't get set.

I'm just thoroughly confused about the whole business of whether (defvar
foo) creates a special variable or not.  At the moment, I'm not even
quite sure any more exactly what a special variable is.  I knew this
morning.  :-(

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-04 22:02               ` Alan Mackenzie
@ 2017-01-04 22:26                 ` Stefan Monnier
  2017-01-04 22:44                   ` Drew Adams
  2017-01-05 10:54                   ` Alan Mackenzie
  0 siblings, 2 replies; 23+ messages in thread
From: Stefan Monnier @ 2017-01-04 22:26 UTC (permalink / raw)
  To: emacs-devel

>> In which context do you need/want to do that (I ask because how to do
>> it (and even if it can be done) depends on the details)?
> I honestly don't know.  I presume that there will be code (other than
> the byte compiler) which will want to make a distinction.

There might, indeed, but it's very rare: in most cases rather than
determining which kind of binding will happen, you want to decide/impose
which binding will happen.

I'm not sure how Common-Lip handles it, but AFAICT there is no
equivalent to special-variable-p there, so they don't seem to offer
a way to find out whether a binding will be lexical or dynamic.

> After (defvar foo), the byte compiler seems able to handle foo as
> a dynamic variable.  I'm still trying to figure out how,

The byte-compiler *sees* the defvar, which lets it keep a note
internally (in a data-structure which keeps track of the current
context, which also includes information about which vars that are
let-bound in the surrounding code were bound lexically, so as to know
when we see a reference to var `foo' whether we should look for `foo' in
the dynamic context or in the lexical context (and if so, where in that
context)).


        Stefan




^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-04 22:26                 ` Stefan Monnier
@ 2017-01-04 22:44                   ` Drew Adams
  2017-01-05 10:54                   ` Alan Mackenzie
  1 sibling, 0 replies; 23+ messages in thread
From: Drew Adams @ 2017-01-04 22:44 UTC (permalink / raw)
  To: Stefan Monnier, emacs-devel

I _almost_ wanted to offer this, as a way to check dynamic vs lexical:

`symbol-value', wrapping with `condition-case', checking for
`void-variable' error and returning `nil' in that case.

But if there are a dynamic var and a lexical var with the same name,
`symbol-value' just sees the former - no real way to test the latter.



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-04 22:26                 ` Stefan Monnier
  2017-01-04 22:44                   ` Drew Adams
@ 2017-01-05 10:54                   ` Alan Mackenzie
  1 sibling, 0 replies; 23+ messages in thread
From: Alan Mackenzie @ 2017-01-05 10:54 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Hello, Stefan.

On Wed, Jan 04, 2017 at 05:26:53PM -0500, Stefan Monnier wrote:
> >> In which context do you need/want to do that (I ask because how to do
> >> it (and even if it can be done) depends on the details)?
> > I honestly don't know.  I presume that there will be code (other than
> > the byte compiler) which will want to make a distinction.

> There might, indeed, but it's very rare: in most cases rather than
> determining which kind of binding will happen, you want to decide/impose
> which binding will happen.

OK.

> I'm not sure how Common-Lip handles it, but AFAICT there is no
> equivalent to special-variable-p there, so they don't seem to offer
> a way to find out whether a binding will be lexical or dynamic.

> > After (defvar foo), the byte compiler seems able to handle foo as
> > a dynamic variable.  I'm still trying to figure out how,

> The byte-compiler *sees* the defvar, which lets it keep a note
> internally (in a data-structure which keeps track of the current
> context, which also includes information about which vars that are
> let-bound in the surrounding code were bound lexically, so as to know
> when we see a reference to var `foo' whether we should look for `foo' in
> the dynamic context or in the lexical context (and if so, where in that
> context)).

Thanks, I'll have a look at that sometime.

>         Stefan

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2017-01-04 20:04           ` Alan Mackenzie
  2017-01-04 21:49             ` Stefan Monnier
@ 2020-02-13 16:42             ` Drew Adams
  2020-02-13 20:02               ` Stefan Monnier
  1 sibling, 1 reply; 23+ messages in thread
From: Drew Adams @ 2020-02-13 16:42 UTC (permalink / raw)
  To: Alan Mackenzie, Stefan Monnier; +Cc: emacs-devel

Coming back to this old thread (2017).

sm> > special-variable-p only indicates if
sm> > (defvar VAR VAL . REST) was evaluated.

And not (defvar VAR), apparently?

am> So it would seem.  There is a bug in the elisp manual, which says that a
am> variable being declared by defvar will cause special-variable-p to
am> return t for it.   The doc string looks right, though far from helpful
am> for anybody who doesn't already know variable binding inside out, and
am> even a bit cryptic for those who do.
am> 
am> special-variable-p would appear to be a near useless function, since it
am> doesn't do what it's name says.
am> 
am> "Defining Variables" in the elisp manual states that "(defvar foo)" makes
am> foo a special variable; yet "(special-variable-p 'foo)" returns nil.  This
am> has got to be a bug, of some sort.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
am> There appears to be no way of checking whether a variable's binding is
am> (or will be) lexical.
am> 
am> I can foresee quite a bit of confusion happening over all this, if it
am> hasn't happened already.
am> 
am> Am I missing something, or is this all really as incoherent as it
am> appears to me?

sm> It's useful for the compiler, but it's mostly internal, indeed.

Reading the doc, a user will have no idea that this
is "internal" mostly or not.  And s?he will have no
idea why (defvar foo) (special-variable-p 'foo)
returns nil.

Can we please fix the doc, to make things clear?

If this function is really (or "mostly"?) internal 
why document it in this way?  Neither the manual
nor the doc string gives a clue about this.

Can we please get the doc to not mislead about this,
at least in some way?



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-13 16:42             ` Drew Adams
@ 2020-02-13 20:02               ` Stefan Monnier
  2020-02-13 20:43                 ` Drew Adams
  0 siblings, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2020-02-13 20:02 UTC (permalink / raw)
  To: Drew Adams; +Cc: Alan Mackenzie, emacs-devel

> Can we please fix the doc, to make things clear?

I added:

    Note that since this is a function, it can only return
    non-@code{nil} for variables which are permanently special, but not
    for those that are only special in the current lexical scope.


-- Stefan




^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-13 20:02               ` Stefan Monnier
@ 2020-02-13 20:43                 ` Drew Adams
  2020-02-13 22:09                   ` Stefan Monnier
  2020-02-13 22:11                   ` Stefan Monnier
  0 siblings, 2 replies; 23+ messages in thread
From: Drew Adams @ 2020-02-13 20:43 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Alan Mackenzie, emacs-devel

> > Can we please fix the doc, to make things clear?
> 
> I added:
> 
>   Note that since this is a function, it can only return
>   non-@code{nil} for variables which are permanently special, but not
>   for those that are only special in the current lexical scope.

Thanks very much for working on this.

But I'm afraid I don't know what a permanent versus
temporary special variable is.  And I haven't found
anything in the doc that has helped me with that.

I looked in Elisp nodes `Using Lexical Binding',
where `special-variable-p' is documented, and
`Defining Variables', where `defvar' is doc'd.
"special" variable seems to be defined as a term
in each of those nodes, BTW.  (I also looked in
node `Variable Scoping'.)

Node `Defining Variables' seems to say that using
`defvar' is enough to make a variable "always"
dynamic:

  The variable is marked as "special", meaning
  that it should always be dynamically bound
                 ^^^^^^
  (*note Variable Scoping::).

Is "always" something different from "permanent"?

Sorry, but I really don't understand what is meant
by what you wrote.  I also don't understand the
implication, "since this is a function".
              ^^^^^
But maybe that's because I don't understand
"permanently special" and "only special in the
current lexical scope".

AFAIK, in Common Lisp a variable is either special
or it's not.  If it is then its binding by `let'
is dynamic, and if it's not then its let-binding
is lexical. (No?)



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-13 20:43                 ` Drew Adams
@ 2020-02-13 22:09                   ` Stefan Monnier
  2020-02-14  1:07                     ` Drew Adams
  2020-02-13 22:11                   ` Stefan Monnier
  1 sibling, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2020-02-13 22:09 UTC (permalink / raw)
  To: Drew Adams; +Cc: Alan Mackenzie, emacs-devel

> But I'm afraid I don't know what a permanent versus
> temporary special variable is.
> And I haven't found
> anything in the doc that has helped me with that.

It's the term used in the part that describes `defvar`:

    Note that specifying a value, even @code{nil}, marks the variable as
    special permanently.  Whereas if @var{value} is omitted then the
    variable is only marked special locally (i.e.@: within the current
    lexical scope, or file if at the top-level).  This can be useful for
    suppressing byte compilation warnings, see @ref{Compiler Errors}.

> AFAIK, in Common Lisp a variable is either special
> or it's not.  If it is then its binding by `let'
> is dynamic, and if it's not then its let-binding
> is lexical. (No?)

Same for us.
Does Common Lisp offer something like `special-variable-p`?


        Stefan




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-13 20:43                 ` Drew Adams
  2020-02-13 22:09                   ` Stefan Monnier
@ 2020-02-13 22:11                   ` Stefan Monnier
  2020-02-14  1:13                     ` Drew Adams
  1 sibling, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2020-02-13 22:11 UTC (permalink / raw)
  To: Drew Adams; +Cc: Alan Mackenzie, emacs-devel

> Sorry, but I really don't understand what is meant
> by what you wrote.  I also don't understand the
> implication, "since this is a function".
>               ^^^^^

A function cannot access the lexical scope of its caller, so a function
cannot know if variable FOO is special in the caller's scope.


        Stefan




^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-13 22:09                   ` Stefan Monnier
@ 2020-02-14  1:07                     ` Drew Adams
  2020-02-14  2:24                       ` Stefan Monnier
  0 siblings, 1 reply; 23+ messages in thread
From: Drew Adams @ 2020-02-14  1:07 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Alan Mackenzie, emacs-devel

> > But I'm afraid I don't know what a permanent versus
> > temporary special variable is.  And I haven't found
> > anything in the doc that has helped me with that.
> 
> It's the term used in the part that describes `defvar`:
> 
>     Note that specifying a value, even @code{nil},
>     marks the variable as special permanently.

Thanks.

[FWIW, I'm no expert in any of this.  I'm just trying
(1) to understand what the Emacs story is about this
and (2) to reconcile that with what I think about the
Common Lisp story about it.  Limited understanding of
both, no doubt.  Also, I'm not arguing for any change,
including a realignment with CL, if there is in fact a
difference.  I just want the doc to be make sense and
be clear about what Emacs does.  So far, it doesn't
seem clear to me.]

____

Permanently is not the opposite of locally.  Instead
of "permanently", shouldn't that text say "globally"?

I think what you mean there is what Common Lisp calls
"indefinite scope" - there are no limits on the scope
of a special variable, i.e., _where_ it can be
referenced.

(As contrasted with "indefinite extent", which is what
lexical bindings provide - no limit on _when_ the var
can be referenced - the binding can last as long as
there is still some reference to the variable.)

If you said "globally" then that text would no longer
seem to directly contradict the statement that "The
variable is marked as 'special', meaning that it
should _always_ be dynamically bound", which is in
the very same node, `Defining Variables'.

But although not seeming to directly contradict, even
that wouldn't really be right, I think.  More correct
would be to say "'special', meaning that it should be
bound dynamically _everywhere_".  Everywhere, not
always.

Dynamic binding, i.e., the binding of a special var,
is indefinite with respect to _where_ (it's global) -
what CL calls "indefinite scope".  And it's dynamic
with respect to _when_ (how long) - what CL calls
"dynamic extent".

Continuing...

>     if @var{value} is omitted then the variable is only
>     marked special locally (i.e.@: within the current
>     lexical scope, or file if at the top-level).

This feature doesn't exist in Common Lisp, AFAIK.    

In CL, `(defvar foo)' _proclaims_ `foo' to be special,
just like `(proclaim (special foo))', and that means
that it's special _everywhere_.

In CL, `defvar' always proclaims the variable special,
whether or not an initial value is provided.  Without
an initial value the variable has no global value and
it's called "unbound".

> > AFAIK, in Common Lisp a variable is either special
> > or it's not.  If it is then its binding by `let'
> > is dynamic, and if it's not then its let-binding
> > is lexical. (No?)
> 
> Same for us.

I don't see that, so far.  I think maybe you're saying
(and perhaps the doc is saying) that a var that is not
bound lexically in some particular context is special
_in that context_ (not everywhere), and that the same
variable can be bound either lexically or dynamically.

And I think that for CL, a variable that is ever
special is always and everywhere special, i.e., in
all contexts.  It's always bound dynamically.

When you say "Same for us", I'm guessing maybe you're
interpreting what I wrote with "special" having your
special ;-) interpretation as being context-dependent:

  "If it is [special] then its binding by `let'
   is dynamic, and if it's not [special] then its
   let-binding is lexical."

Am I guessing right wrt your interpretation of
"special"?  For you (and thus Emacs terminology),
can a var be sometimes special and sometimes not?

I don't think that's the case for the way CL uses
"special variable".

However, CL does say that about a given _name_ of
a variable.  The same name can refer in some places
to a special var and in other places to a lexical
var.  This is what CLTL says:

  At any given time either or both kinds of variable
  with the same name may have a current value.
  Which of the two kinds of variable is referred to
  when a symbol is evaluated depends on the context
  of the evaluation.

  The general rule is that if the symbol occurs
  textually within a program construct that creates
  a _binding_ for a variable of the same name, then
  the reference is to the variable specified by the
  binding; if no such program construct textually
  contains the reference, then it is taken to refer
  to the special variable of that name.

IOW, there can be a special variable `foo' and one
or more lexical variables `foo'.  They have the same
name but they're different variables.

I think the terminology you're using would say that
it's the same variable, and it's sometimes, or in
some places, special and at other times, or in other
places, lexical.

> Does Common Lisp offer something like `special-variable-p`?

Not that I know of.  But it also doesn't use `defvar'
with and without second arg to declare specialness.
`defvar' always declares specialness (proclaims,
actually).



^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-13 22:11                   ` Stefan Monnier
@ 2020-02-14  1:13                     ` Drew Adams
  0 siblings, 0 replies; 23+ messages in thread
From: Drew Adams @ 2020-02-14  1:13 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Alan Mackenzie, emacs-devel

> > Sorry, but I really don't understand what is meant
> > by what you wrote.  I also don't understand the
> > implication, "since this is a function".
> >               ^^^^^
> 
> A function cannot access the lexical scope of its caller, so a function
> cannot know if variable FOO is special in the caller's scope.

Right. (See my other reply, for how CL would
say that: it can't know whether the symbol
FOO refers to the special var FOO or a lexical
var FOO.)

I think it would be clearer to just say that
`special-variable-p' can't know whether its
arg refers to a special variable.

But I think that brings us back to what Alan
said: it's apparently useless, since that's
what it claims to do (even by just its name).

To which you replied that the function is
"mostly internal" (which is mostly vague).

So far, it sounds to me like this function
(1) should have an "internal"-advertising
name, (double hyphens) if any function should,
and (2) it shouldn't even be mentioned in the
manual.  Any mention of it seems like an
invitation to use it and be confused in its
use.

Or if it should be mentioned, it's not yet
clear to me what its semi-internal use case
is, and why that should be communicated to
users in the manual.  What will they (users)
do with it?



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-14  1:07                     ` Drew Adams
@ 2020-02-14  2:24                       ` Stefan Monnier
  2020-02-14 17:25                         ` Drew Adams
  0 siblings, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2020-02-14  2:24 UTC (permalink / raw)
  To: Drew Adams; +Cc: Alan Mackenzie, emacs-devel

> Permanently is not the opposite of locally.  Instead
> of "permanently", shouldn't that text say "globally"?

Feel free to provide a patch that tries to clarify.  Part of the issue
is that (defvar VAR VAL) is just like (defvar VAR) when it's "processed"
by the byte-compiler: it won't affect bindings of VAR everywhere but
only within the corresponding lexical scope.  But when (defvar VAR VAL)
is *executed* then it subsequently will affect all interpreted code and
all the code that is subsequently compiled in that same Emacs session,
whereas *executing* (defvar VAR VAL) only affects the code subsequently
interpreted, and only within the current lexical scope.

> I think what you mean there is what Common Lisp calls
> "indefinite scope" - there are no limits on the scope
> of a special variable, i.e., _where_ it can be
> referenced.

That sounds about right, yes.

> ... the statement that "The variable is marked as 'special', meaning
> that it should _always_ be dynamically bound"

I'm not very happy with this statement, indeed: "always" isn't
quite right.

>>     if @var{value} is omitted then the variable is only
>>     marked special locally (i.e.@: within the current
>>     lexical scope, or file if at the top-level).
> This feature doesn't exist in Common Lisp, AFAIK.

AFAIK, in CL you can get something similar with (declare (special foo)).

> In CL, `defvar' always proclaims the variable special,
> whether or not an initial value is provided.

Indeed, Elisp is slightly different in this respect.

> And I think that for CL, a variable that is ever
> special is always and everywhere special, i.e., in
> all contexts.  It's always bound dynamically.

In Common Lisp

   (list
     (lambda (x)
       (let ((y x))
         (declare (special y))
         (lambda (z) (+ y z))))
     (lambda (x)
       (let ((y x))
         (lambda (z) (+ y z)))))

gives you two functions that don't behave the same because the `y`
binding in the first is dynamically scoped whereas that same `y` binding
is statically scoped in the second.

> When you say "Same for us", I'm guessing maybe you're interpreting
> what I wrote with "special" having your special ;-) interpretation as
> being context-dependent:

No, I'm saying that there's more to it than just either always or
never.  E.g. in Common Lisp after the system has *compiled* a chunk of
code with (defvar VAR ...), VAR may or may not be special (i.e. the
`defvar` must have affected the compiled code, but not necessarily the
state of the system that compiled the file).
[ In Elisp, the situation is somewhat similar, tho a bit
  less undefined.  ]

>> Does Common Lisp offer something like `special-variable-p`?
> Not that I know of.

Indeed.  And for good reasons: being a function it's hard to make it
provide the kind of semantic you expect from it, given the complexity
and scope-sensitivity of "specialness".

> But it also doesn't use `defvar' with and without second arg to
> declare specialness.

That's just a superficial syntactic difference.

Maybe the slightly deeper difference is that Common Lisp doesn't have
a way to say "all bindings of VAR under the current scope should be
dynamic", like (defvar VAR) does.  Instead it has (declare (special VAR))
which only talks about one particular binding.  But both Elisp's
`defvar` and CL's `declare` introduce the same issue that specialness is
not all-or-nothing and that a plain function like `special-variable-p`
can't give quite the answer we'd ideally want.


        Stefan




^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-14  2:24                       ` Stefan Monnier
@ 2020-02-14 17:25                         ` Drew Adams
  2020-02-14 19:19                           ` Stefan Monnier
  2020-02-17 18:23                           ` Drew Adams
  0 siblings, 2 replies; 23+ messages in thread
From: Drew Adams @ 2020-02-14 17:25 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Alan Mackenzie, emacs-devel

> > Permanently is not the opposite of locally.  Instead
> > of "permanently", shouldn't that text say "globally"?
> 
> Feel free to provide a patch that tries to clarify.

That will have to come from someone who understands
this better than I.  I'm hoping to understand it a
bit better from this thread, and then, hopefully,
from an updated doc.

> Part of the issue
> is that (defvar VAR VAL) is just like (defvar VAR) when it's "processed"
> by the byte-compiler: it won't affect bindings of VAR everywhere but
> only within the corresponding lexical scope.  But when (defvar VAR VAL)
> is *executed* then it subsequently will affect all interpreted code and
> all the code that is subsequently compiled in that same Emacs session,
> whereas *executing* (defvar VAR VAL) only affects the code subsequently
> interpreted, and only within the current lexical scope.

I'm not sure how that relates to permanently vs globally,
but OK, thanks.

> >>     if @var{value} is omitted then the variable is only
> >>     marked special locally (i.e.@: within the current
> >>     lexical scope, or file if at the top-level).
> > This feature doesn't exist in Common Lisp, AFAIK.
> 
> AFAIK, in CL you can get something similar with
> (declare (special foo)).

Yes, similar, but not exactly the same.  In CL, such
a declaration can only be used, I think, within
(certain) special forms.

In particular, I don't think there's any equivalent
for Emacs's file-local scope (other than putting the
declaration in a top-level `let', or similar - a
top-level `(locally (declare (special foo)))' perhaps).
But maybe I'm wrong about this.

The real point was about `defvar'.  CL's `defvar' is
not Emacs's, AFAIU.

> > In CL, `defvar' always proclaims the variable special,
> > whether or not an initial value is provided.
> 
> Indeed, Elisp is slightly different in this respect.

The key word there is "proclaim".  Function `proclaim':

https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node104.html.

  "The function `proclaim' takes a DECL-SPEC as its
   argument and puts it into effect globally."

  "As a special case (so to speak), `proclaim' treats a
   `special' DECL-SPEC as applying to all bindings as
   well as to all references of the mentioned variables."

  "For example, after `(proclaim '(special x))' in a
   function definition such as `(defun example (x) ...)'
   the parameter X will be bound as a special (dynamic)
   variable rather than as a lexical (static) variable."

That's what CL `defvar' does - it declares the var to
be special, i.e., dynamic, everywhere.  There's no
shadowing (unlike the case for other proclamations).

  "`(defvar variable)' proclaims variable to be
   special (see `proclaim'), and may perform other
   system-dependent bookkeeping actions."

https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node67.html

> > And I think that for CL, a variable that is ever
> > special is always and everywhere special, i.e., in
> > all contexts.  It's always bound dynamically.
> 
> In Common Lisp
> 
>    (list
>      (lambda (x)
>        (let ((y x))
>          (declare (special y))
>          (lambda (z) (+ y z))))
>      (lambda (x)
>        (let ((y x))
>          (lambda (z) (+ y z)))))
> 
> gives you two functions that don't behave the same because the `y`
> binding in the first is dynamically scoped whereas that same `y`
> binding is statically scoped in the second.

In CL parlance, those are not only not the same binding,
they are not the same variable `y'.  That's the point.

The same symbol (name) is used for those two different
`y' variables, but they're different vars (for CL).

The first variable named `y' is special, which means
that it's special everywhere (indefinite scope), and
it's duration is the duration of the executing code
that uses it (dynamic extent).

> I'm saying that there's more to it than just either always or
> never.  E.g. in Common Lisp after the system has *compiled* a chunk of
> code with (defvar VAR ...), VAR may or may not be special (i.e. the
> `defvar` must have affected the compiled code, but not necessarily the
> state of the system that compiled the file).

Again, I think maybe you're thinking of VAR being
occurrences of VAR as a symbol, as opposed to the
variable that's declared ("created" in a sense, but
not necessarily assigned a value - it might have
no value, i.e., in CL-speak, be "unbound").

The effect on the compiled code gets to the use
of the actual variable that was declared special.
And yes, occurrences of other, different variables
with the same name are not special.  Not only
"might not be special", but cannot be special -
there is only ever one special variable with a
given name.

(Again, this is my understanding.  It may be wrong.)

> [ In Elisp, the situation is somewhat similar, tho a bit
>   less undefined. ]
> 
> >> Does Common Lisp offer something like `special-variable-p`?
> > Not that I know of.
> 
> Indeed.  And for good reasons: being a function it's hard to make it
> provide the kind of semantic you expect from it, given the complexity
> and scope-sensitivity of "specialness".

I fully agree about that (as far as my understanding goes).
 
> > But it also doesn't use `defvar' with and without second arg to
> > declare specialness.
> 
> That's just a superficial syntactic difference.
> 
> Maybe the slightly deeper difference is that Common Lisp doesn't have
> a way to say "all bindings of VAR under the current scope should be
> dynamic", like (defvar VAR) does.  Instead it has (declare (special VAR))
> which only talks about one particular binding.

I don't think that's right, but perhaps I don't
follow you correctly.

CL's `defvar' _proclaims_ the variable to be
special (dynamic) - and the scope of that is
indefinite - unlimited.  It's not a lexical
scope (this binding or this file).

> But both Elisp's `defvar` and CL's `declare` introduce
> the same issue that specialness is not all-or-nothing

Dunno what that means, but I'm guessing that the
difference in how we're talking about this is
maybe the difference between how CL talks about
a "variable".

For the CL doc, a special variable is special
everywhere - no lexical scoping for it at all,
and its extent (lifetime) is dynamic.  And as a
consequence, there is only ever a single special
variable with any given name (symbol).  Its
bindings are always dynamic. Its scope remains
indefinite.

> and that a plain function like `special-variable-p`
> can't give quite the answer we'd ideally want.

On that we agree.
___


Which brings us back to the beginning: 

Maybe remove `special-variable-p' altogether?
Or if, as is apparently the case, it's needed for
the byte-compiler implementation, at least rename
it to indicate that it's internal, and remove it
from the manual?

I'm not trying to remake the Emacs design of
lexical scoping - or anything like that.  I'm
not even trying to change how it's presented in
the doc (though maybe from this thread you'll
have some slight changes you'd like to make).

This is really only about `special-variable-p'.
Both its name and its doc are currently quite
misleading.  And it doesn't seem like something
that users will ever use or should ever try to
use.  I've asked about that use case...



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-14 17:25                         ` Drew Adams
@ 2020-02-14 19:19                           ` Stefan Monnier
  2020-02-17 18:23                           ` Drew Adams
  1 sibling, 0 replies; 23+ messages in thread
From: Stefan Monnier @ 2020-02-14 19:19 UTC (permalink / raw)
  To: Drew Adams; +Cc: Alan Mackenzie, emacs-devel

> The real point was about `defvar'.  CL's `defvar' is
> not Emacs's, AFAIU.

That's a given.  But I thought the point was about Emacs's doc.

>> In Common Lisp
>> 
>>    (list
>>      (lambda (x)
>>        (let ((y x))
>>          (declare (special y))
>>          (lambda (z) (+ y z))))
>>      (lambda (x)
>>        (let ((y x))
>>          (lambda (z) (+ y z)))))
>> 
>> gives you two functions that don't behave the same because the `y`
>> binding in the first is dynamically scoped whereas that same `y`
>> binding is statically scoped in the second.
>
> In CL parlance, those are not only not the same binding,
> they are not the same variable `y'.  That's the point.

Not really, no: what the user wants to know is "when I write (let ((y
...)) ...), when will binding be dynamic or lexical".
Whether or not it's "the same variable" as some other
is irrelevant, or more specifically, it just shifts the problem.

> The first variable named `y' is special, which means
> that it's special everywhere (indefinite scope), and
> it's duration is the duration of the executing code
> that uses it (dynamic extent).

E.g. here it just shifts the problem from "which y will be lexical and
which will be dynamic" to "which y corresponds to this one-and-only
special var and which doesn't".


        Stefan




^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical.
  2020-02-14 17:25                         ` Drew Adams
  2020-02-14 19:19                           ` Stefan Monnier
@ 2020-02-17 18:23                           ` Drew Adams
  1 sibling, 0 replies; 23+ messages in thread
From: Drew Adams @ 2020-02-17 18:23 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Alan Mackenzie, emacs-devel

ping.

> Which brings us back to the beginning:
> 
> Maybe remove `special-variable-p' altogether?
> Or if, as is apparently the case, it's needed for
> the byte-compiler implementation, at least rename
> it to indicate that it's internal, and remove it
> from the manual?
> 
> I'm not trying to remake the Emacs design of
> lexical scoping - or anything like that.  I'm
> not even trying to change how it's presented in
> the doc (though maybe from this thread you'll
> have some slight changes you'd like to make).
> 
> This is really only about `special-variable-p'.
> Both its name and its doc are currently quite
> misleading.  And it doesn't seem like something
> that users will ever use or should ever try to
> use.  I've asked about that use case...



^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2020-02-17 18:23 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-03 14:14 Can't M-x compile-defun `edebug' because dynamic variables are falsely taken as lexical Alan Mackenzie
2017-01-03 18:35 ` Stefan Monnier
2017-01-03 21:32   ` Alan Mackenzie
2017-01-03 21:48     ` Stefan Monnier
2017-01-04 13:39       ` Alan Mackenzie
2017-01-04 15:23         ` Stefan Monnier
2017-01-04 20:04           ` Alan Mackenzie
2017-01-04 21:49             ` Stefan Monnier
2017-01-04 22:02               ` Alan Mackenzie
2017-01-04 22:26                 ` Stefan Monnier
2017-01-04 22:44                   ` Drew Adams
2017-01-05 10:54                   ` Alan Mackenzie
2020-02-13 16:42             ` Drew Adams
2020-02-13 20:02               ` Stefan Monnier
2020-02-13 20:43                 ` Drew Adams
2020-02-13 22:09                   ` Stefan Monnier
2020-02-14  1:07                     ` Drew Adams
2020-02-14  2:24                       ` Stefan Monnier
2020-02-14 17:25                         ` Drew Adams
2020-02-14 19:19                           ` Stefan Monnier
2020-02-17 18:23                           ` Drew Adams
2020-02-13 22:11                   ` Stefan Monnier
2020-02-14  1:13                     ` Drew Adams

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).