unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#9469: buffer-local variables seem to remember previous values
@ 2011-09-10 17:07 Le Wang
  2011-09-10 17:44 ` Drew Adams
  0 siblings, 1 reply; 24+ messages in thread
From: Le Wang @ 2011-09-10 17:07 UTC (permalink / raw)
  To: 9469

I've reproed in both Emacs 23.3 and bzr build from a few days ago both
on windows.

Steps:

1. emacs -Q

2. eval this region:

(setq buf-a (create-file-buffer "a"))

(setq foo nil)
(make-variable-buffer-local 'foo)

(defun test1 ()
  (interactive)
  (let (alist)
    (push '(:var . 0) alist)
    (with-current-buffer buf-a
      (setq foo alist))))

(defun test2 ()
  (interactive)
  (with-current-buffer buf-a
    (setcdr (assq :var foo) 20)))

(defun show ()
  (interactive)
  (with-current-buffer buf-a
    (format "    ; foo in 'a' is %s" foo)))

(defun test3 ()
  (interactive)
  (let (alist)
    (push `(:var . ,(+ 0)) alist)
    (with-current-buffer buf-a
      (setq foo alist))))


(test1)
(test2)
(test1)
(insert (show))
(test3)
(insert (show))

Note results on both `insert' lines should be identical but the first
insert some how remembers a previous value.  I find it surprising that
no one has ever come across this before.

-- 
Le





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-10 17:07 bug#9469: buffer-local variables seem to remember previous values Le Wang
@ 2011-09-10 17:44 ` Drew Adams
  2011-09-11 16:57   ` Le Wang
  0 siblings, 1 reply; 24+ messages in thread
From: Drew Adams @ 2011-09-10 17:44 UTC (permalink / raw)
  To: 'Le Wang', 9469

> 1. emacs -Q
> 2. eval this region:
> (setq buf-a (create-file-buffer "a"))
> (setq foo nil)
> (make-variable-buffer-local 'foo)
> (defun test1 ()
>   (interactive)
>   (let (alist)
>     (push '(:var . 0) alist)
>     (with-current-buffer buf-a
>       (setq foo alist))))
> (defun test2 ()
>   (interactive)
>   (with-current-buffer buf-a
>     (setcdr (assq :var foo) 20)))
> (defun show ()
>   (interactive)
>   (with-current-buffer buf-a
>     (format "    ; foo in 'a' is %s" foo)))
> (defun test3 ()
>   (interactive)
>   (let (alist)
>     (push `(:var . ,(+ 0)) alist)
>     (with-current-buffer buf-a
>       (setq foo alist))))
> 
> (test1)
> (test2)
> (test1)
> (insert (show))
> (test3)
> (insert (show))
> 
> Note results on both `insert' lines should be identical but the first
> insert some how remembers a previous value.  I find it surprising that
> no one has ever come across this before.

No, they should not be identical.  This is a classic Lisp gotcha.

(test1) sets buffer-local var `foo' to a new alist ((:var . 0)).
(test2) sets the cdr of the single element of that alist to 20.
That means that `foo' in buf-a is now ((:var . 20)).
(test1) then creates a new alist and pushes the _same_ cons, (:var . 20) onto
it.
And it sets `foo' to this new alist.

If you were to use (cons :var 0) instead of '(:var . 0) then you would not be
reusing the same cons cell.

Note that different Lisps (and different implementations of the same Lisp) can
treat a sexp such as '(a b) differently - they might or might not create a new
list each time it is read or eval'd.

To be sure to get what you expect in situations like this, do not use '(...).
Use `cons' or `list' or equivalent backquote syntax.  Do not expect '(...) to
create new list structure each time it is read/eval'd.






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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-10 17:44 ` Drew Adams
@ 2011-09-11 16:57   ` Le Wang
  2011-09-11 17:56     ` Drew Adams
  0 siblings, 1 reply; 24+ messages in thread
From: Le Wang @ 2011-09-11 16:57 UTC (permalink / raw)
  To: Drew Adams; +Cc: 9469

On Sun, Sep 11, 2011 at 1:44 AM, Drew Adams <drew.adams@oracle.com> wrote:
> No, they should not be identical.  This is a classic Lisp gotcha.

Thanks for the pointer, Drew.

I was unable to google up any information regarding this as being a
classic gotcha.  Do you have any references?

If this is in fact "by design", then the manual should definitely say
so in the quoting section.  Do I have to follow a different procedure
to file a documentation bug?

-- 
Le





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-11 16:57   ` Le Wang
@ 2011-09-11 17:56     ` Drew Adams
  2011-09-11 18:08       ` Andreas Schwab
  0 siblings, 1 reply; 24+ messages in thread
From: Drew Adams @ 2011-09-11 17:56 UTC (permalink / raw)
  To: 'Le Wang'; +Cc: 9469

> > No, they should not be identical.

BTW, I should have said "It is not the case that they should be identical."  Not
quite the same thing.  There is no "should" here.  AFAIK, most Lisps do not
prescribe the behavior in this regard - it is up to the implementation.  But I'm
no expert on just what various Lisps define wrt this.

> > This is a classic Lisp gotcha.
> Thanks for the pointer, Drew.
> 
> I was unable to google up any information regarding this as being a
> classic gotcha.  Do you have any references?

No, I would have to google also.  I said it's "classic", which probably really
means that I was bitten by the same gotcha many, many moon ago, and I learned my
lesson then, in discussion with people who knew Lisp well.

Well, a quick google of "lisp quote list" brings me to this:
http://stackoverflow.com/questions/134887/when-to-use-quote-in-lisp

Search that page for "DO NOT USE QUOTE TO CREATE LISTS THAT YOU WILL LATER
MODIFY".  It says, "The spec allows the compiler to treat quoted lists as
constants."  I guess it  might be referring to the Common Lisp spec; dunno.

Scroll down further to the explanation by Matthias Benkard.  He points out that
when you use (quote (a b c)) the list (a b c) is created (the first time) by the
Lisp loader or reader, not by `quote'.  `quote' just returns that already
existing list.  `quote' does not create new list structure (or new symbols or
new strings or...).

You can probably find other, similar explanations by googling.

The real lesson, I think, is what I said earlier, which works for all Lisps: Do
not expect `quote' to create new list structure.

> If this is in fact "by design", then the manual should definitely say
> so in the quoting section.  Do I have to follow a different procedure
> to file a documentation bug?

I don't think the Elisp manual should say anything about it, but I'll let others
decide that.

The takeaway is, I think, that you should not depend on '(...) to create new
list structure each time it is evaluated.  I suppose the manual could say that.
Or it could perhaps clarify that `quote' does not create new Lisp objects; it
just returns the object that is its argument, unevaluated.  What can confuse
people is that the object already exists; it is provided by the reader (or the
loader).

I guess you could say that the reader treats list notation it encounters
similarly to what it does for symbol notation: if a symbol with the encountered
name already exists then it uses ("returns") that symbol.  Otherwise, it first
creates a symbol with that name.  IOW, the reader `intern's names it encounters.
Similarly, it handles list notation it encounters by either creating a new list
or returning an existing one.

Again, I'm no expert on this.  Perhaps someone else can explain it better.






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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-11 17:56     ` Drew Adams
@ 2011-09-11 18:08       ` Andreas Schwab
  2011-09-11 18:49         ` Le Wang
  0 siblings, 1 reply; 24+ messages in thread
From: Andreas Schwab @ 2011-09-11 18:08 UTC (permalink / raw)
  To: Drew Adams; +Cc: 9469, 'Le Wang'

This has nothing to do with the use of quote, but with the use of
destructive functions (setcdr) on a shared data structure.

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] 24+ messages in thread

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-11 18:08       ` Andreas Schwab
@ 2011-09-11 18:49         ` Le Wang
  2011-09-11 18:54           ` Lars Magne Ingebrigtsen
  2011-09-11 19:46           ` Andreas Schwab
  0 siblings, 2 replies; 24+ messages in thread
From: Le Wang @ 2011-09-11 18:49 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: 9469

On Mon, Sep 12, 2011 at 2:08 AM, Andreas Schwab <schwab@linux-m68k.org> wrote:
> This has nothing to do with the use of quote, but with the use of
> destructive functions (setcdr) on a shared data structure.

Of course you're technically right, but should the manual mention in
the "quoting" section that using quote the way I did results in a
shared data structure?  This part was surprising to me.

And I think it will be very surprising to others new to lisp.
Specifically, if you read the stackexchange thread Drew pointed to:
http://stackoverflow.com/questions/134887/when-to-use-quote-in-lisp

It seems I'm not the only one who didn't realize that quote does not cons.

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

-- 
Le





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-11 18:49         ` Le Wang
@ 2011-09-11 18:54           ` Lars Magne Ingebrigtsen
  2011-09-11 19:18             ` Le Wang
  2011-09-11 19:37             ` Helmut Eller
  2011-09-11 19:46           ` Andreas Schwab
  1 sibling, 2 replies; 24+ messages in thread
From: Lars Magne Ingebrigtsen @ 2011-09-11 18:54 UTC (permalink / raw)
  To: Le Wang; +Cc: Andreas Schwab, 9469

Le Wang <l26wang@gmail.com> writes:

>> This has nothing to do with the use of quote, but with the use of
>> destructive functions (setcdr) on a shared data structure.
>
> Of course you're technically right, but should the manual mention in
> the "quoting" section that using quote the way I did results in a
> shared data structure?  This part was surprising to me.

If I read your code correctly, Andreas is correct and precise as usual,
if a bit terse.  :-)

The thing you're seeing has absolutely nothing to do with the use of
quote.

You're destructively altering a single list and expecting to see the
list be different in various buffers.

-- 
(domestic pets only, the antidote for overdose, milk.)
  bloggy blog http://lars.ingebrigtsen.no/





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-11 18:54           ` Lars Magne Ingebrigtsen
@ 2011-09-11 19:18             ` Le Wang
  2011-09-11 19:54               ` Lars Magne Ingebrigtsen
  2011-09-11 19:37             ` Helmut Eller
  1 sibling, 1 reply; 24+ messages in thread
From: Le Wang @ 2011-09-11 19:18 UTC (permalink / raw)
  To: Lars Magne Ingebrigtsen; +Cc: Andreas Schwab, 9469

On Mon, Sep 12, 2011 at 2:54 AM, Lars Magne Ingebrigtsen <larsi@gnus.org> wrote:
> If I read your code correctly, Andreas is correct and precise as usual,
> if a bit terse.  :-)

Ok, that was my fault.  I didn't know how to make heads or tails of
the situation, so included some red herrings in my original snippet.
This should clarify my exact point of confusion:

(setq foo-alist nil)
	;; => nil

(defun reset-var-in-foo-alist ()
  (push '(:var . 0) foo-alist))
	;; => reset-var-in-foo-alist

(defun increment-var-in-foo-alist ()
  (let ((var-cons (assq :var foo-alist)))
    (setcdr var-cons (1+ (cdr var-cons)))))
	;; => increment-var-in-foo-alist


(reset-var-in-foo-alist)
	;; => ((:var . 0))
(increment-var-in-foo-alist)
	;; => 1
(reset-var-in-foo-alist)
	;; => ((:var . 1) (:var . 1))


Again, my misunderstanding was that in `reset-var-in-foo-alist' quote
does not cons, I assumed it did.

-- 
Le





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-11 18:54           ` Lars Magne Ingebrigtsen
  2011-09-11 19:18             ` Le Wang
@ 2011-09-11 19:37             ` Helmut Eller
  1 sibling, 0 replies; 24+ messages in thread
From: Helmut Eller @ 2011-09-11 19:37 UTC (permalink / raw)
  To: 9469

* Lars Magne Ingebrigtsen [2011-09-11 18:54] writes:

> Le Wang <l26wang@gmail.com> writes:
>
>>> This has nothing to do with the use of quote, but with the use of
>>> destructive functions (setcdr) on a shared data structure.
>>
>> Of course you're technically right, but should the manual mention in
>> the "quoting" section that using quote the way I did results in a
>> shared data structure?  This part was surprising to me.
>
> If I read your code correctly, Andreas is correct and precise as usual,
> if a bit terse.  :-)
>
> The thing you're seeing has absolutely nothing to do with the use of
> quote.
>
> You're destructively altering a single list and expecting to see the
> list be different in various buffers.

Well, quote is tricky!  It wouldn't hurt to point out that modifying a
quoted list often means modifying your code.  E.g.

(defun foo () 
  (let ((list '(1 2 3)))
    (setcdr list (cddr list))))

(equal (copy-tree (symbol-function 'foo))
       (progn
	 (foo)
	 (symbol-function 'foo)))

returns nil.  I think few beginners will see that using setcdr here not
only modifies the value stored in the variable list but also modifies
the s-exp stored in 'foo.

Helmut






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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-11 18:49         ` Le Wang
  2011-09-11 18:54           ` Lars Magne Ingebrigtsen
@ 2011-09-11 19:46           ` Andreas Schwab
  1 sibling, 0 replies; 24+ messages in thread
From: Andreas Schwab @ 2011-09-11 19:46 UTC (permalink / raw)
  To: Le Wang; +Cc: 9469

Le Wang <l26wang@gmail.com> writes:

> It seems I'm not the only one who didn't realize that quote does not cons.

 -- Special Form: quote object
     This special form returns OBJECT, without evaluating it.

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] 24+ messages in thread

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-11 19:18             ` Le Wang
@ 2011-09-11 19:54               ` Lars Magne Ingebrigtsen
  2011-09-12  4:39                 ` Le Wang
  0 siblings, 1 reply; 24+ messages in thread
From: Lars Magne Ingebrigtsen @ 2011-09-11 19:54 UTC (permalink / raw)
  To: Le Wang; +Cc: Andreas Schwab, 9469

Le Wang <l26wang@gmail.com> writes:

> Again, my misunderstanding was that in `reset-var-in-foo-alist' quote
> does not cons, I assumed it did.

Ok.  So I'm closing this report.

-- 
(domestic pets only, the antidote for overdose, milk.)
  bloggy blog http://lars.ingebrigtsen.no/





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-11 19:54               ` Lars Magne Ingebrigtsen
@ 2011-09-12  4:39                 ` Le Wang
  2011-09-12  7:57                   ` Andreas Schwab
  2011-09-13 12:54                   ` Stefan Monnier
  0 siblings, 2 replies; 24+ messages in thread
From: Le Wang @ 2011-09-12  4:39 UTC (permalink / raw)
  To: Lars Magne Ingebrigtsen; +Cc: Andreas Schwab, 9469

On Mon, Sep 12, 2011 at 3:54 AM, Lars Magne Ingebrigtsen <larsi@gnus.org> wrote:
>
> Ok.  So I'm closing this report.

First of all, it's entirely possible that in order to preserve my self
perception that "I am smart", my ego won't let me admit that I just
wasn't smart enough parse the manual properly.

However, I still think it's not spelled out clearly enough.  It needs
an example to clearly show the trap.

"The special form quote returns its single argument, as written,
without evaluating it. This provides a way to include constant symbols
and lists"

Isn't the first sentence misleading?  It does not *always* return a
single argument as written.  It does the first time, and memoizes
subsequently.  Where is the mention of that?

The second sentence clarifies that quote should be used for "constant
symbols and lists".

Again, pedantically speaking, the information is there.  It's just not
clear enough to prevent other people falling into this trap in the
future.  I'm happy to leave this bug closed, or work with someone
specifically responsible for the Emacs Lisp Manual to come up with a
clear small example.


>
> --
> (domestic pets only, the antidote for overdose, milk.)
>  bloggy blog http://lars.ingebrigtsen.no/
>



-- 
Le





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-12  4:39                 ` Le Wang
@ 2011-09-12  7:57                   ` Andreas Schwab
  2011-09-12  8:23                     ` Le Wang
  2011-09-13 12:54                   ` Stefan Monnier
  1 sibling, 1 reply; 24+ messages in thread
From: Andreas Schwab @ 2011-09-12  7:57 UTC (permalink / raw)
  To: Le Wang; +Cc: Lars Magne Ingebrigtsen, 9469

Le Wang <l26wang@gmail.com> writes:

> "The special form quote returns its single argument, as written,
> without evaluating it. This provides a way to include constant symbols
> and lists"
>
> Isn't the first sentence misleading?  It does not *always* return a
> single argument as written.  It does the first time, and memoizes
> subsequently.  Where is the mention of that?

Since the argument does not change, how is that wrong?

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] 24+ messages in thread

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-12  7:57                   ` Andreas Schwab
@ 2011-09-12  8:23                     ` Le Wang
  2011-09-12  8:35                       ` Andreas Schwab
  0 siblings, 1 reply; 24+ messages in thread
From: Le Wang @ 2011-09-12  8:23 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Lars Magne Ingebrigtsen, 9469

On Mon, Sep 12, 2011 at 3:57 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
> Since the argument does not change, how is that wrong?

Yes, I understand from a functional programming perspective, it's
perfectly fine.  You're right.  but you're still being pedantic.
Maybe setcdr the way I did was not very lisp-y.  I willingly concede
I'm a lisp novice, and I'm used to thinking in a more procedural way.
My point is that the manual would be more helpful to someone in my
position if it had an example saying don't modify quoted objects, and
why.

Anyway, if it's the opinion of the maintainers that the manual is fine
as it is, it's fine with me.

Thanks you for looking into this issue, and working on Emacs!

-- 
Le





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-12  8:23                     ` Le Wang
@ 2011-09-12  8:35                       ` Andreas Schwab
  2011-09-12 14:30                         ` Drew Adams
  2011-09-12 15:06                         ` Le Wang
  0 siblings, 2 replies; 24+ messages in thread
From: Andreas Schwab @ 2011-09-12  8:35 UTC (permalink / raw)
  To: Le Wang; +Cc: Lars Magne Ingebrigtsen, 9469

Le Wang <l26wang@gmail.com> writes:

> My point is that the manual would be more helpful to someone in my
> position if it had an example saying don't modify quoted objects, and
> why.

This has nothing at all to do with quoting.  Don't use destructive
functions if you don't know what you are doing.  If you store through a
pointer in C you also have to take care of side effects.  There is
nothing new here.

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] 24+ messages in thread

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-12  8:35                       ` Andreas Schwab
@ 2011-09-12 14:30                         ` Drew Adams
  2011-09-12 15:06                         ` Le Wang
  1 sibling, 0 replies; 24+ messages in thread
From: Drew Adams @ 2011-09-12 14:30 UTC (permalink / raw)
  To: 'Andreas Schwab', 'Le Wang'
  Cc: 'Lars Magne Ingebrigtsen', 9469

> > My point is that the manual would be more helpful to someone in my
> > position if it had an example saying don't modify quoted 
> > objects, and why.
> 
> This has nothing at all to do with quoting.  Don't use destructive
> functions if you don't know what you are doing.

Everything that people have said in the thread is true.  That doesn't mean that
we can't help users more in this regard.

What could perhaps be made clearer in the manual - and perhaps in the Lisp Intro
manual (e.g., with pedagogic examples), is the role of the Lisp reader in
creating list structure, symbols, etc.  It is ignorance of or forgetting about
this feature of Lisp that confuses users (esp. newbies) when it comes to `quote'
etc.

Explanation of Lisp reading is far removed in the manual from the description of
`quote' (and they are not directly related, so there is nothing wrong with
this).  It might help to (a) develop the reader-creates-objects subject in the
Lisp Intro manual and (b) put a reminder about this in the section about
`quote', with a caveat about modifying etc.

In sum, it's not about whether you or the manual or Le is right or wrong.  It's
about helping users.  And yes, this is a potential point of confusion.  The
consequences of the Lisp reader creating things are not necessarily obvious to
newbies.






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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-12  8:35                       ` Andreas Schwab
  2011-09-12 14:30                         ` Drew Adams
@ 2011-09-12 15:06                         ` Le Wang
  1 sibling, 0 replies; 24+ messages in thread
From: Le Wang @ 2011-09-12 15:06 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Lars Magne Ingebrigtsen, 9469

On Mon, Sep 12, 2011 at 4:35 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:
> This has nothing at all to do with quoting.  Don't use destructive
> functions if you don't know what you are doing.  If you store through a
> pointer in C you also have to take care of side effects.  There is
> nothing new here.

This discussion has turned in a different direction.  I've filed doc
bug #9482, with some more details.  The maintainers can decide what to
do with it.

-- 
Le





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-12  4:39                 ` Le Wang
  2011-09-12  7:57                   ` Andreas Schwab
@ 2011-09-13 12:54                   ` Stefan Monnier
  2011-09-13 13:12                     ` Le Wang
                                       ` (2 more replies)
  1 sibling, 3 replies; 24+ messages in thread
From: Stefan Monnier @ 2011-09-13 12:54 UTC (permalink / raw)
  To: Le Wang; +Cc: Lars Magne Ingebrigtsen, Andreas Schwab, 9469

> "The special form quote returns its single argument, as written,
> without evaluating it. This provides a way to include constant symbols
> and lists"

> Isn't the first sentence misleading?  It does not *always* return a
> single argument as written.  It does the first time, and memoizes
> subsequently.  Where is the mention of that?

There is no memoization: the quote does not *construct* the object, it
just returns it.

The problem is similar/identical to what happens with immediate strings in C:

char *foo (void)
{
    char *res = "toto\n";
    res[1]++;
    return res;
}

[ modern C tries to fix this problem by the use of "const char*". ]

> Again, pedantically speaking, the information is there.  It's just not
> clear enough to prevent other people falling into this trap in the
> future.

I'd be happy to try and make it more clear to people who aren't familiar
with it (after all, that's the main target audience here), but I'm not
sure how.

Do you have some suggestion about what text to use to make it clear to you?


        Stefan





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-13 12:54                   ` Stefan Monnier
@ 2011-09-13 13:12                     ` Le Wang
  2011-09-13 15:00                     ` Helmut Eller
  2011-09-13 18:02                     ` Johan Bockgård
  2 siblings, 0 replies; 24+ messages in thread
From: Le Wang @ 2011-09-13 13:12 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Lars Magne Ingebrigtsen, Andreas Schwab, 9469

On Tue, Sep 13, 2011 at 8:54 PM, Stefan Monnier
<monnier@iro.umontreal.ca> wrote:
> Do you have some suggestion about what text to use to make it clear to you?

I filed documentation bug 9482, I I will suggest specific text there.

-- 
Le





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-13 12:54                   ` Stefan Monnier
  2011-09-13 13:12                     ` Le Wang
@ 2011-09-13 15:00                     ` Helmut Eller
  2011-09-13 18:02                     ` Johan Bockgård
  2 siblings, 0 replies; 24+ messages in thread
From: Helmut Eller @ 2011-09-13 15:00 UTC (permalink / raw)
  To: 9469

* Stefan Monnier [2011-09-13 12:54] writes:

> I'd be happy to try and make it more clear to people who aren't familiar
> with it (after all, that's the main target audience here), but I'm not
> sure how.

I think a section "Lisp pitfalls" in the manual would be about right for
this.  That could contain examples and explanations like modifying
quoted lists or using #'delete without storing the result with setq and
other such misunderstandings.  Then add references from the description
for quote to the pitfalls section.

Helmut






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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-13 12:54                   ` Stefan Monnier
  2011-09-13 13:12                     ` Le Wang
  2011-09-13 15:00                     ` Helmut Eller
@ 2011-09-13 18:02                     ` Johan Bockgård
  2011-09-13 18:52                       ` Drew Adams
  2011-09-15 18:14                       ` Le Wang
  2 siblings, 2 replies; 24+ messages in thread
From: Johan Bockgård @ 2011-09-13 18:02 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Lars Magne Ingebrigtsen, Andreas Schwab, 9469, Le Wang

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> "The special form quote returns its single argument, as written,
>> without evaluating it. This provides a way to include constant symbols
>> and lists"
>
>> Isn't the first sentence misleading?  It does not *always* return a
>> single argument as written.  It does the first time, and memoizes
>> subsequently.  Where is the mention of that?
>
> There is no memoization: the quote does not *construct* the object, it
> just returns it.

I think the "as written" bit is mildly confusing, and nearly falls into
this trap:

    In other languages, an expression is text; it has no other form. In
    Lisp, an expression is primarily a Lisp object and only secondarily
    the text that is the object's read syntax. Often there is no need to
    emphasize this distinction, but you must keep it in the back of your
    mind, or you will occasionally be very confused.

        -- (info "(elisp) Printed Representation")





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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-13 18:02                     ` Johan Bockgård
@ 2011-09-13 18:52                       ` Drew Adams
  2011-09-13 20:42                         ` Helmut Eller
  2011-09-15 18:14                       ` Le Wang
  1 sibling, 1 reply; 24+ messages in thread
From: Drew Adams @ 2011-09-13 18:52 UTC (permalink / raw)
  To: 'Johan Bockgård', 'Stefan Monnier'
  Cc: 'Lars Magne Ingebrigtsen', 'Andreas Schwab', 9469,
	'Le Wang'

> I think the "as written" bit is mildly confusing, and nearly 
> falls into this trap:
> 
>     In other languages, an expression is text; it has no 
>     other form. In Lisp, an expression is primarily a Lisp
>     object

Indeed.  And I repeat that the misunderstanding comes from not knowing or not
sufficiently appreciating where those objects come from: what creates them.

That is what it would help to repeat/emphasize in the doc (e.g., in the context
of things like `quote', at least via a cross-reference).

Users need of course to understand that `quote' just returns its argument, but
that is not really the problem here, since they can misunderstand "its argument"
per the confusion that Johan referred to (text vs Lisp object).

What users might not get is that the argument that `quote' receives is a Lisp
object that has already been created.  That might not be obvious to someone new
to Lisp.  Especially when written as ', it is easy to misunderstand `quote' as
applying to the textual sexp that follows it, and not to a Lisp object.

The Lisp reader is kind of in the background of user awareness, so the question
of where the Lisp object comes from can mistakenly be answered by thinking that
it is `quote' that creates it based on the text/sexp that follows the '.  That,
I think, is the gotcha that tripped up Le (and he's not alone).

In the case of a literal list argument to `quote', e.g. (quote (a b c)), users
need to understand that the Lisp reader (or loader) creates the list (a b c).

Given that understanding, what can also be missing is that, depending on the
Lisp, the Lisp reader might not create a _new_ list each time it encounters the
sexp "(a b c)".  And in Emacs Lisp it in fact does not create a new list; it
reuses a previously created list, if available.  (Is that always true for Elisp?
What about gc?).

This too is not obvious.  And we can point out that literal strings are treated
differently - the reader does create a new, `eq'-unique string each time it sees
"abc".  The bottom line is that we should communicate the lesson that you should
not depend on the Lisp reader creating a new object each time it reads a sexp.

It would be helpful to mention this and explain that the reader's treatment of
list sexps is similar to its treatment of symbol sexps (names).  The treatment
of symbols is perhaps a bit easier to understand because we introduce the notion
of obarray, and because a symbol itself has an explicit string representation
(its name).

At a minimum, then, the manual's treatment of `quote' (and perhaps other things)
should reference some doc that explains the Lisp reader behavior well.






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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-13 18:52                       ` Drew Adams
@ 2011-09-13 20:42                         ` Helmut Eller
  0 siblings, 0 replies; 24+ messages in thread
From: Helmut Eller @ 2011-09-13 20:42 UTC (permalink / raw)
  To: 9469

* Drew Adams [2011-09-13 18:52] writes:

[...]
> The Lisp reader is kind of in the background of user awareness, so the
> question of where the Lisp object comes from can mistakenly be
> answered by thinking that it is `quote' that creates it based on the
> text/sexp that follows the '.  That, I think, is the gotcha that
> tripped up Le (and he's not alone).

Yes, that's crucial.  Beginners need to understand that read and eval
are separate and what the purpose of each is: read turns text into
s-expressions.  eval "executes" s-expressions; eval is described in
terms of s-expressions and not text.  Also that the reader is not the
only way to construct s-expressions for eval.

[...]
> Given that understanding, what can also be missing is that, depending
> on the Lisp, the Lisp reader might not create a _new_ list each time
> it encounters the sexp "(a b c)".  And in Emacs Lisp it in fact does
> not create a new list; it reuses a previously created list, if
> available.  (Is that always true for Elisp?  What about gc?).

I've never heard of a reader that does what you describe here.  The
reader creates a new list for "'foo" just as for "(quote foo)" or for
"(bar foo)".

(eq (read "'a") (read "'a")) returns nil; all the time.

Just like
(let ((sexp (read "('a 'a)")))
  (eq (car sexp) 
      (cadr sexp)))
is always nil.

The reader interns symbols but lists and vectors are freshly created
(ignoring the #1# syntax for now).  The compiler may coalesce constant
lists that are equal; but don't let us confuse the reader with the
compiler.

Helmut






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

* bug#9469: buffer-local variables seem to remember previous values
  2011-09-13 18:02                     ` Johan Bockgård
  2011-09-13 18:52                       ` Drew Adams
@ 2011-09-15 18:14                       ` Le Wang
  1 sibling, 0 replies; 24+ messages in thread
From: Le Wang @ 2011-09-15 18:14 UTC (permalink / raw)
  To: Johan Bockgård; +Cc: Lars Magne Ingebrigtsen, Andreas Schwab, 9469

On Wed, Sep 14, 2011 at 2:02 AM, Johan Bockgård <bojohan@gnu.org> wrote:
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> There is no memoization: the quote does not *construct* the object, it
>> just returns it.
>
> I think the "as written" bit is mildly confusing, and nearly falls into
> this trap:
>
>    In other languages, an expression is text; it has no other form. In
>    Lisp, an expression is primarily a Lisp object and only secondarily
>    the text that is the object's read syntax. Often there is no need to
>    emphasize this distinction, but you must keep it in the back of your
>    mind, or you will occasionally be very confused.
>
>        -- (info "(elisp) Printed Representation")

This is kind of funny.  Stefan and Andreas basically kept saying quote
just returns the thing, but doesn't construct it.  My mind couldn't
grasp what that means.

The reader is the chasm that I just couldn't cross.  In my mind a
program describes how something happens, it isn't the thing that
happens.  "(quote (a b))", `quote' is a function that returns a
reference to something.  And for it to return the same reference, then
it must be memoizing based on the inputs.

The passage Johan posted along with Drew's explanation has enlightened
me.  Thank you all.

-- 
Le





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

end of thread, other threads:[~2011-09-15 18:14 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-10 17:07 bug#9469: buffer-local variables seem to remember previous values Le Wang
2011-09-10 17:44 ` Drew Adams
2011-09-11 16:57   ` Le Wang
2011-09-11 17:56     ` Drew Adams
2011-09-11 18:08       ` Andreas Schwab
2011-09-11 18:49         ` Le Wang
2011-09-11 18:54           ` Lars Magne Ingebrigtsen
2011-09-11 19:18             ` Le Wang
2011-09-11 19:54               ` Lars Magne Ingebrigtsen
2011-09-12  4:39                 ` Le Wang
2011-09-12  7:57                   ` Andreas Schwab
2011-09-12  8:23                     ` Le Wang
2011-09-12  8:35                       ` Andreas Schwab
2011-09-12 14:30                         ` Drew Adams
2011-09-12 15:06                         ` Le Wang
2011-09-13 12:54                   ` Stefan Monnier
2011-09-13 13:12                     ` Le Wang
2011-09-13 15:00                     ` Helmut Eller
2011-09-13 18:02                     ` Johan Bockgård
2011-09-13 18:52                       ` Drew Adams
2011-09-13 20:42                         ` Helmut Eller
2011-09-15 18:14                       ` Le Wang
2011-09-11 19:37             ` Helmut Eller
2011-09-11 19:46           ` Andreas Schwab

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