[Top][All Lists]

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

Re: Rant - Elisp terminology is deceptive

From: David Kastrup
Subject: Re: Rant - Elisp terminology is deceptive
Date: Sun, 25 Jan 2015 10:16:59 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux)

Kelly Dean <address@hidden> writes:

> David Kastrup wrote:
>> A buffer does not have an "environment".
> What do you call the thing that lists the bindings of buffer-local
> variables to values? The standard term for a list of bindings of
> variables to values that's used for resolving variable references,
> both in Lisp and elsewhere, is ‟environment”.
>> It has a list of global variable values
>> to substitute whenever it is made current.
> You mean like a closure can have? (A closure's environment can also have 
> variables with names that aren't names of global variables, but that's not 
> the point here.)
> (setq foo
>       (lexical-let ((shift-select-mode 'bar))
>       (lambda () shift-select-mode)))
> (funcall foo) → bar

Closures nest.  Buffers don't.  And there always is one current buffer.
Closures are part of a lexical environment.  Buffers aren't.

>> buffer-local variables _are_ buffer-local versions of _global_
>> variables.
> shift-select-mode above is a closure-local version of a global
> variable.

Not at all.  It is not related to the global variable in any way.  If
you do
(disassemble (byte-compile foo)) you get

byte code:
  args: (&rest --cl-rest--)
0       constant  apply
1       constant  <compiled-function>
      args: (G42200)
    0       varref    G42200
    1       symbol-value 
    2       return    

2       constant  --shift-select-mode--
3       varref    --cl-rest--
4       call      3
5       return    

which is rather awful.  But the salient point is that
--shift-select-mode-- is a generated symbol (with value 'bar) not in any
way related to the global variable shift-select-mode.

>> With setq-default you are not setting
>> a value that is in any manner more or less global than a buffer-local
>> setting.
> setq-default sets the global variable, which is visible in other
> buffers (unless they shadow it with their own buffer-locals).
> A buffer-local variable is not visible in other buffers.

The default value and the global value are part of the same symbol and
accessed with different commands.

> I don't know how buffer-locals are implemented internally, but from a
> user's (and Elisp programmer's) point of view, a buffer has an
> environment with variables that shadow global variables.

Again, the buffer does not provide scoping.  It is the setting of
(current-buffer) that decides which buffer-local values are active.

> If the value of each variable in that environment is stored as part of
> the structure that stores the value of the same-named global variable
> rather than being stored in a separate list of bindings for the
> environment, that's irrelevant. The effect is the same.

There is no nesting of scopes involved here.  At any given time, only
one buffer's global variable are active.  That is similar to global
static variables in C: they are not nested.  Instead, one compilation
unit at a time may provide a value.  C does not have defaults for global
static variables: it is an error to declare the same name as global
external and global static.

Elisp, in contrast, provides two value slots for that purpose.

> The help system agrees with me. It doesn't call buffer-locals
> ‟global”. It _contrasts_ buffer-locals and
> globals. E.g. describe-variable for mark-active tells me: mark-active
> is a variable defined in `buffer.c'.  Its value is t Local in buffer
> *Help*; global value is nil

It does not seem like a good idea to spread the confusion, however.

David Kastrup

reply via email to

[Prev in Thread] Current Thread [Next in Thread]