* `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
* Re: `setplist' on local var escaping let binding
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
0 siblings, 1 reply; 8+ messages in thread
From: Stefan Monnier @ 2010-10-21 1:10 UTC (permalink / raw)
To: MON KEY; +Cc: emacs-devel
> I noticed today that if I `setplist' on a null let bound local var
The above shows a misunderstanding: setplist does not operate on
variables but on symbols.
Stefan
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `setplist' on local var escaping let binding
2010-10-21 1:10 ` Stefan Monnier
@ 2010-10-21 3:02 ` MON KEY
2010-10-21 4:26 ` Stephen J. Turnbull
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: MON KEY @ 2010-10-21 3:02 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
On Wed, Oct 20, 2010 at 9:10 PM, Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
>> I noticed today that if I `setplist' on a null let bound local var
>
> The above shows a misunderstanding: setplist does not operate on
> variables but on symbols.
What is this then: 'a-quoted-variable-but-not-a-symbol ?
Are you saying that `setplist' is only for top-level symbols?
Doesn't quoting the variable intern?
(let (ms)
(setplist 'ms '(can-has a-plist))
`(,(get 'ms 'can-has)
,(intern-soft "ms" obarray)))
;=> (a-plist ms)
(get 'ms 'can-has)
;=> a-plist
Appears to.
Whichever. I still don't understand how/why following happens
(nor how your answer addresses it):
(progn
(unintern "ms" obarray)
(let (ms)
(setplist 'ms '(can-has a-plist))
`(,(get 'ms 'can-has)
,(intern-soft "ms" obarray))))
(a-plist nil)
;=> (a-plist nil)
(get 'ms 'can-has)
;=> nil
So what am i missing?
In following `ms' is a "thing-like" bound to an uninterned "non-thing"
`bubba'. `ms' is on obarray `bubba' isn't and his symbol-value void.
(let ((ms (make-symbol "bubba")))
(list :thing-like (intern-soft "ms" obarray)
:non-thing (intern-soft "bubba" obarray)))
;=> (:thing-like ms :non-thing nil)
make sure its all clear:
(progn
(intern-soft "bubba" obarray)
(unintern "bubba" obarray)
(intern-soft "ms" obarray)
(unintern "ms" obarray))
In following the "non-thing" `bubba' has a plist and the thing-like is interned:
(let ((ms (make-symbol "bubba")))
(apply #'setplist
(list (eval (list 'quote (identity ms)))
'(not a symbol really?)))
`(:non-thing-bubba ,(not (intern-soft "bubba" obarray))
:but-with-a-plist ,(apply #'get
(list (eval (list 'quote (identity ms)))
'symbol))
:is-thing-like-ms ,(eq (intern-soft "ms" obarray)
(intern-soft "ms" obarray))))
;=> (:non-thing-bubba t
; :but-with-a-plist really\?
; :is-thing-like-ms t)
> Stefan
--
/s_P\
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `setplist' on local var escaping let binding
2010-10-21 3:02 ` MON KEY
@ 2010-10-21 4:26 ` Stephen J. Turnbull
2010-10-21 9:06 ` Andreas Schwab
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Stephen J. Turnbull @ 2010-10-21 4:26 UTC (permalink / raw)
To: MON KEY; +Cc: Stefan Monnier, emacs-devel
MON KEY writes:
> What is this then: 'a-quoted-variable-but-not-a-symbol ?
> Are you saying that `setplist' is only for top-level symbols?
> Doesn't quoting the variable intern?
Sure, as you demonstrated. But you're asking the wrong question. The
question is "where does `let' intern?"
(I take no position on what behavior is correct, except to note that
XEmacs behaves the way GNU Emacs does, FWIW YMMV.)
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `setplist' on local var escaping let binding
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
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Andreas Schwab @ 2010-10-21 9:06 UTC (permalink / raw)
To: MON KEY; +Cc: Stefan Monnier, emacs-devel
MON KEY <monkey@sandpframing.com> writes:
> What is this then: 'a-quoted-variable-but-not-a-symbol ?
It is a list consisting the symbols quote and
a-quoted-variable-but-not-a-symbol.
> Are you saying that `setplist' is only for top-level symbols?
What is a "top-level symbol"?
> Doesn't quoting the variable intern?
The only instances that interns symbols are the lisp reader and the
function intern.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `setplist' on local var escaping let binding
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
4 siblings, 0 replies; 8+ messages in thread
From: Davis Herring @ 2010-10-21 12:46 UTC (permalink / raw)
To: MON KEY; +Cc: Stefan Monnier, emacs-devel
> (progn
> (unintern "ms" obarray)
> (let (ms)
> (setplist 'ms '(can-has a-plist))
> `(,(get 'ms 'can-has)
> ,(intern-soft "ms" obarray))))
> (a-plist nil)
Symbols are created (or retrieved) when a form is read, so the rest of
this form is still using the old ms. Your life will be much simpler if
you forget that `unintern' exists at all. If you want to have a dynamic
mapping where it's important to remove elements, just use a hash table.
> (let ((ms (make-symbol "bubba")))
> (apply #'setplist
> (list (eval (list 'quote (identity ms)))
> '(not a symbol really?)))
> `(:non-thing-bubba ,(not (intern-soft "bubba" obarray))
> :but-with-a-plist ,(apply #'get
> (list (eval (list 'quote (identity ms)))
> 'symbol))
> :is-thing-like-ms ,(eq (intern-soft "ms" obarray)
> (intern-soft "ms" obarray))))
You continue to use `identity' for no reason, and seem to have discovered
an even more verbose synonym for nothing: (eval (list 'quote foo)) is
exactly equivalent to foo. (apply #'foo (list bar baz)) is also just the
same as (foo bar baz), and `obarray' is the default argument to the
interning functions. All :symbols evaluate to themselves, so you can
finally write (with about half the characters)
(let ((ms (make-symbol "bubba")))
(setplist ms '(not a symbol really?))
(list :non-thing-bubba (not (intern-soft "bubba"))
:but-with-a-plist (get ms 'symbol)
:is-thing-like-ms (eq (intern-soft "ms") (intern-soft "ms"))))
at which point the only remaining quarrels are your use of "thing" and
"non-thing" (but surely that's just the result of the confusion, not the
cause) and your apparent suspicion that `intern-soft''s value will change
between two adjacent calls.
It's really not that confusing if you don't make it so!
Davis
--
This product is sold by volume, not by mass. If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `setplist' on local var escaping let binding
2010-10-21 3:02 ` MON KEY
` (2 preceding siblings ...)
2010-10-21 12:46 ` Davis Herring
@ 2010-10-21 13:35 ` Thien-Thi Nguyen
2010-10-21 18:38 ` Stefan Monnier
4 siblings, 0 replies; 8+ messages in thread
From: Thien-Thi Nguyen @ 2010-10-21 13:35 UTC (permalink / raw)
To: MON KEY; +Cc: Stefan Monnier, emacs-devel
() MON KEY <monkey@sandpframing.com>
() Wed, 20 Oct 2010 23:02:07 -0400
What is this then: 'a-quoted-variable-but-not-a-symbol ?
That depends on who reads it, and when.
It's kind of a moo[dt] question. :-D
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: `setplist' on local var escaping let binding
2010-10-21 3:02 ` MON KEY
` (3 preceding siblings ...)
2010-10-21 13:35 ` Thien-Thi Nguyen
@ 2010-10-21 18:38 ` Stefan Monnier
4 siblings, 0 replies; 8+ messages in thread
From: Stefan Monnier @ 2010-10-21 18:38 UTC (permalink / raw)
To: MON KEY; +Cc: emacs-devel
> What is this then: 'a-quoted-variable-but-not-a-symbol ?
There's no such thing as "a quoted variable".
Stefan
^ 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 external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.