unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* `setplist' on local var escaping let binding
@ 2010-10-20 23:28 MON KEY
  2010-10-21  1:10 ` Stefan Monnier
  0 siblings, 1 reply; 8+ messages in thread
From: MON KEY @ 2010-10-20 23:28 UTC (permalink / raw)
  To: emacs-devel

I noticed today that if I `setplist' on a null let bound local var
inside a call to `with-current-buffer' the symbol's property list can
escape the scope of the let binding. This happens in one case but not
in another.  I can't figure out why.

Does elisp treat a symbol's plist as a global resource distinct from
its value cell?

The Common Lisp ANSI spec has this to say w/re `symbol-plist':

,----
| The use of `setf' should be avoided, since a symbol's property list
| is a global resource that can contain information established and
| depended upon by unrelated programs in the same Lisp image.
`----

I reviewed the Emacs Lisp specification :P for a similarly equivalent
cautionary missive but I still can't tell if this is a bug or not.

So, I'm asking here.

Following is an attempt at illustrating what is happening:

(progn
  (unintern "local-var" obarray)
  (let (local-var)
    (with-temp-buffer
      (setplist 'local-var '(prop1 1 prop2 2 prop3 3))
      (symbol-plist 'local-var))))
;=> (prop1 1 prop2 2 prop3 3)

> (symbol-plist 'local-var)
;=> nil

Now unintern the `local-var' symbol:

(unintern "local-var" obarray)
;=> t

Following expression also puts properties on `local-var', but this
time its properties "escape" the let-binding:

(progn
  (ignore)
  (let (local-var)
    (with-temp-buffer
      (setplist 'local-var '(prop1 1 prop2 2 prop3 3))
      (symbol-plist 'local-var))))
;=> (prop1 1 prop2 2 prop3 3)

(symbol-plist 'local-var)
;=> (prop1 1 prop2 2 prop3 3)

This seems either wrong or inconsisistent because `local-var' was
well... local. I would expect the symbol-plist to also return nil
outside the let binding as it did in the first example.

I thought maybe the issue was around `with-temp-buffer' so I tried this:

(with-current-buffer
    (get-buffer-create "*fresh-buffer-for-local-var*")
  (progn
    (unintern "local-var" obarray)
    (let (local-var)
      (with-temp-buffer
        (setplist 'local-var '(prop1 1 prop2 2 prop3 3))
        (symbol-plist 'local-var)))))
;=> (prop1 1 prop2 2 prop3 3)

(symbol-plist 'local-var)
;=> nil

To mimic `with-temp-buffer' macro rid the "temp-buffer" w/:

(kill-buffer (get-buffer-create "*fresh-buffer-for-local-var*"))

Also, to meake sure that `local-var' is really dead:
(unintern "local-var" obarray)

Trying the same, but without uninterning `local-var' inside `progn':

(with-current-buffer
    (get-buffer-create "*fresh-buffer-for-local-var*")
  (progn
    (ignore)
    (let (local-var)
      (with-temp-buffer
        (setplist 'local-var '(prop1 1 prop2 2 prop3 3))
        (symbol-plist 'local-var)))))
;=> (prop1 1 prop2 2 prop3 3)

(symbol-plist 'local-var)
;=> (prop1 1 prop2 2 prop3 3)

Now without the `progn' wrapper but keeping the `unintern':

(with-current-buffer
    (get-buffer-create "*fresh-buffer-for-local-var*")
  (unintern "local-var" obarray)
  (let (local-var)
    (with-temp-buffer
      (setplist 'local-var '(prop1 1 prop2 2 prop3 3))
      (symbol-plist 'local-var))))
;=> (prop1 1 prop2 2 prop3 3)

(symbol-plist 'local-var)
;=> nil

Again, just to be sure, rid any possibility that `local-var' is
lingering in some unseen Emacs crevice:

(kill-buffer (get-buffer-create "*fresh-buffer-for-local-var*"))
(unintern "local-var" obarray)

Now, without the `progn' wrapper and without the `unintern':

(with-current-buffer
    (get-buffer-create "*fresh-buffer-for-local-var*")
  (let (local-var)
    (with-temp-buffer
      (setplist 'local-var '(prop1 1 prop2 2 prop3 3))
      (symbol-plist 'local-var))))
;=> (prop1 1 prop2 2 prop3 3)

(symbol-plist 'local-var)
;=> (prop1 1 prop2 2 prop3 3)

I've verified the above behavior w/ emacs -Q

(emacs-version)
;=> "GNU Emacs 23.2.1 (i686-pc-linux-gnu, GTK+ Version 2.20.0)
;    of 2010-05-10"

It seems fair to assume that neither the special form `progn' nor the
macro `with-temp-buffer' are causing the divergent behavior.

So, what gives?

Is there something happening around forms containing `unintern'/`let'
which allow a null symbols's plist to return to nil whereas it
otherwise won't?

And, more specifically what is the correct behavior?

Is it expected that every interned symbol's plist should have global
extent independent of its scope?

I ask because I'm interested to learn how this may affect the
proposed integration of the lexbind?

If what I have pointed out above is some sort of bug (abstract though
it may be) my suspicion is that the "problem" originates with the
priveleged space Emacs' extends to buffers. No doubt this extension
has been reasonable where the buffer is a primary data-structure for
Emacs the _text editor_. However, if there is to be a lexbind, does
this not imply a certain acknowledgement that Emacs is also a
_programming language_?

There is a tension here around buffer/text-editor vs. expressions/lisp

Indeed, I've been informed by at least one emacs-devel that,
 "Emacs is a _text editor_ not a programming language"

Is it not unreasonable to assume that some aspects of the buffers
priveleged status _must_ move over to make room for the lexbind?

IOW will any more "space" be affored Emacs lisp-lists or will the
buffer continue on as the primary "owner" of variable extent/scope?

--
/s_P\



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

end of thread, other threads:[~2010-10-21 18:38 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-20 23:28 `setplist' on local var escaping let binding MON KEY
2010-10-21  1:10 ` Stefan Monnier
2010-10-21  3:02   ` MON KEY
2010-10-21  4:26     ` Stephen J. Turnbull
2010-10-21  9:06     ` Andreas Schwab
2010-10-21 12:46     ` Davis Herring
2010-10-21 13:35     ` Thien-Thi Nguyen
2010-10-21 18:38     ` Stefan Monnier

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).