* binding question
@ 2013-10-06 9:35 Eric Abrahamsen
2013-10-06 10:14 ` Thien-Thi Nguyen
2013-10-06 12:39 ` Michael Heerdegen
0 siblings, 2 replies; 5+ messages in thread
From: Eric Abrahamsen @ 2013-10-06 9:35 UTC (permalink / raw)
To: help-gnu-emacs
I've got a variable binding scenario that I thought would be easy to
resolve, but is giving me trouble. I have the feeling that this scenario
represents some sort of Lesson 1 in How Bindings Work, but I'm still not
sure of the proper solution.
The general situation is: I want to start with a list template stored in
a variable. Another function in this library starts with the template,
modifies it a few times, then does something with the modified version.
Every time this function is called, it should start with a "fresh" copy
of the template.
Clearly the following doesn't work: it actually modifies the original
list-template.
(defvar list-template
'(item ((with . "some")
(sub . "lists"))
nil (other things will go here)))
(defun main-entry-function ()
;; obviously this doesn't work as defvars are always special
(let ((list-template list-template))
;; list-template is accessed dynamically in the following functions
(modify-list-template)
(modify-list-template-again)
(do-something-with-modified-list-template)))
The other option would be to pass list-template as an argument to each
of these functions. I guess each call would then have to look like:
(setq list-template (modify-list-template list-template))
This seems ugly, and it won't necessarily be easy to ensure the
modifying functions end by returning the new value of list-template.
What's the best way of handling this? And is there one "right" solution
for both dynamic and lexical binding?
Thanks!
Eric
PS: The wiki[1] mentions pretty much exactly my scenario, but doesn't
actually say what should be done.
[1]
http://www.emacswiki.org/emacs/DynamicBindingVsLexicalBinding#toc4
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: binding question
2013-10-06 9:35 binding question Eric Abrahamsen
@ 2013-10-06 10:14 ` Thien-Thi Nguyen
2013-10-06 14:03 ` Eric Abrahamsen
2013-10-06 14:45 ` Stefan Monnier
2013-10-06 12:39 ` Michael Heerdegen
1 sibling, 2 replies; 5+ messages in thread
From: Thien-Thi Nguyen @ 2013-10-06 10:14 UTC (permalink / raw)
To: Eric Abrahamsen; +Cc: help-gnu-emacs
[-- Attachment #1: Type: text/plain, Size: 755 bytes --]
() Eric Abrahamsen <eric@ericabrahamsen.net>
() Sun, 06 Oct 2013 17:35:30 +0800
What's the best way of handling this?
Check out ‘copy-tree’, e.g.:
(let ((list-template (copy-tree list-template)))
...)
See also:
http://www.emacswiki.org/emacs/ElispCookbook
which compares ‘copy-sequence’ and ‘copy-tree’ in section "Copying".
WRT, lexical vs dynamic binding, the code is written to assume dynamic
binding, so you might want to explicitly set ‘lexical-binding’ to nil
somewhere.
--
Thien-Thi Nguyen
GPG key: 4C807502
(if you're human and you know it)
read my lisp: (responsep (questions 'technical)
(not (via 'mailing-list)))
=> nil
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: binding question
2013-10-06 9:35 binding question Eric Abrahamsen
2013-10-06 10:14 ` Thien-Thi Nguyen
@ 2013-10-06 12:39 ` Michael Heerdegen
1 sibling, 0 replies; 5+ messages in thread
From: Michael Heerdegen @ 2013-10-06 12:39 UTC (permalink / raw)
To: help-gnu-emacs
Hi Eric,
in LISP, lists (cons cells) are passed by reference. Thus, different
bindings can refer to the same list object, like here the variables a
and b:
(setq a '(1 2))
(setq b a) ; copies the reference to the list, not the list itself
(setcar a 'foo)
b
==> (foo 2)
> (defun main-entry-function ()
> ;; obviously this doesn't work as defvars are always special
> (let ((list-template list-template))
This creates a new local binding, but it references the same list object
in memory. If you change the structure of the referenced object, the
change is "visible" for all variables which are bound to this object.
You can create a real copy of the object with `copy-tree'. Or don't
destructively alter the list, but process the value with
non-destructive functions instead.
I'm sure there is a good explanation somewhere in the manual.
Regards,
Michael.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: binding question
2013-10-06 10:14 ` Thien-Thi Nguyen
@ 2013-10-06 14:03 ` Eric Abrahamsen
2013-10-06 14:45 ` Stefan Monnier
1 sibling, 0 replies; 5+ messages in thread
From: Eric Abrahamsen @ 2013-10-06 14:03 UTC (permalink / raw)
To: help-gnu-emacs
Thien-Thi Nguyen <ttn@gnu.org> writes:
> () Eric Abrahamsen <eric@ericabrahamsen.net>
> () Sun, 06 Oct 2013 17:35:30 +0800
>
> What's the best way of handling this?
>
> Check out ‘copy-tree’, e.g.:
>
> (let ((list-template (copy-tree list-template)))
> ...)
>
> See also:
>
> http://www.emacswiki.org/emacs/ElispCookbook
>
> which compares ‘copy-sequence’ and ‘copy-tree’ in section "Copying".
>
> WRT, lexical vs dynamic binding, the code is written to assume dynamic
> binding, so you might want to explicitly set ‘lexical-binding’ to nil
> somewhere.
Thanks very much to both of you! Copying sounds like exactly what I
wanted.
I was sort of wondering if there was a one-size-fits-all solution that
would also work in future lexically-bound environments, but I guess that
really would require passing arguments.
Thanks again,
Eric
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: binding question
2013-10-06 10:14 ` Thien-Thi Nguyen
2013-10-06 14:03 ` Eric Abrahamsen
@ 2013-10-06 14:45 ` Stefan Monnier
1 sibling, 0 replies; 5+ messages in thread
From: Stefan Monnier @ 2013-10-06 14:45 UTC (permalink / raw)
To: help-gnu-emacs
> WRT, lexical vs dynamic binding, the code is written to assume dynamic
> binding, so you might want to explicitly set ‘lexical-binding’ to nil
> somewhere.
Better than set lexical-binding to nil is to add (defvar <foo>) at the
beginning of the file for every variable <foo> which is used via
dynamic scoping.
Stefan
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-10-06 14:45 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-06 9:35 binding question Eric Abrahamsen
2013-10-06 10:14 ` Thien-Thi Nguyen
2013-10-06 14:03 ` Eric Abrahamsen
2013-10-06 14:45 ` Stefan Monnier
2013-10-06 12:39 ` Michael Heerdegen
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).