help-gnu-emacs
[Top][All Lists]
Advanced

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

Re: Is add-to-list supposed to work when lexical-binding is t?


From: Kelly Dean
Subject: Re: Is add-to-list supposed to work when lexical-binding is t?
Date: Wed, 5 Jun 2013 16:12:09 -0700 (PDT)

Stefan Monnier wrote:
>> Section 11.9.3 (Lexical Binding) in the manual says "functions like
>> `symbol-value', `boundp', and `set' only retrieve or modify
>> a variable's dynamic binding".  Why?
>
>Because a variable is not the same thing as a symbol.
>
>For dynamic binding, you can somewhat blur the difference and use the
>symbol's value cell as "the content of the variable of that name"
>because let-binding just temporarily changes the only global value.
>
>With lexical scoping, a given variable name can have many different
>values at the same time so this is not an option.

I read the last bit as, "with lexical scoping, a given symbol (symbolic name) 
can be interpreted as many different variables in different scopes (and each 
variable can have multiple instances) ...", to synchronize terminology. And I 
call the things that variables are bound to "instances", not "bindings" like 
the docs do.

In the scope of (let ((x 'a)) ...) with lexical binding enabled, since the 
symbol x is interpreted as a lexical variable rather than as the global 
variable (the latter bound to the global instance, the value cell for the 
symbol x), I propose a quote-lex special form, where (quote-lex x), with e.g. 
"&x" or maybe "^x" as readable syntax, returns a reference to the current 
instance (current in time and recursion level) of the lexical variable, like 
"&x" does in C, instead of returning the symbol x (which, without context, is a 
reference to the global instance). Also change the set function to accept not 
only symbols, but also lexical instance references, and change symbol-value to 
either return the value of a symbol's value cell as usual if given the symbol, 
or return the value of a lexical instance if given a reference to the latter.

Then you could use argument-mutating functions, including the standard 
add-to-list function, without having to convert them into macros, and do e.g.:
(let ((x '(a))) (add-to-list &x 'b) x) -> (b a)

The pair of closures produced by wrap-lexical in my previous message (but the 
first closure should more simply be just the plain value; oops) imitates what I 
propose; a special form would be needed to actually return a reference to the 
lexical instance itself. My set-passed-lexical and get-passed-lexical imitate 
what I propose for set and symbol-value.

Furthermore, instead of having a separate quote-lex, maybe overload quote, and 
return the symbol as usual where it's used as the global variable, or return a 
reference to the current lexical instance where the symbol is used as a lexical 
variable. Then even current code that uses argument-mutating functions could be 
used unmodified, instead of having to convert their relevant uses of quote to 
quote-lex. And lexical binding won't cause the accidents I described in my 
previous message.

If overloading quote is a bad idea, then quote-lex should return a reference to 
the current instance of the given variable regardless of whether it's given a 
lexical or global variable; that means in the latter case, it does the same 
thing as quote, which means quote-lex can be used instead of quote in all 
places, except where a symbol needs to be returned despite that symbol also 
serving as a lexical variable in the same scope, because the symbol will be 
used as the global variable or as something other than a variable.

>> (let ((x '(a))) (add-to-list 'x 'b) x) -> (b a)
>
>Yup, this is asking for trouble.  Use `push' or `cl-pushnew' instead.

So, converting every argument-mutating function into a macro actually _is_ the 
right thing to do? That seems unnecessarily complicated, just a way of working 
around the lack of lexical quoting.




reply via email to

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