GNU bug report logs -
#30078
27.0.50; Use lexical-binding for M-:
Previous Next
Reported by: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
Date: Thu, 11 Jan 2018 16:38:01 UTC
Severity: wishlist
Found in version 27.0.50
Fixed in version 27.1
Done: Glenn Morris <rgm <at> gnu.org>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 30078 in the body.
You can then email your comments to 30078 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Thu, 11 Jan 2018 16:38:01 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Stefan Monnier <monnier <at> IRO.UMontreal.CA>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Thu, 11 Jan 2018 16:38:01 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
Package: Emacs
Version: 27.0.50
I think we should slowly move towards making lexical-binding the default
and we could start by making M-: always use lexical binding.
WDYT?
Stefan
diff --git a/lisp/simple.el b/lisp/simple.el
index 4c69e0f6ff..fa31ef9f0f 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1608,12 +1608,12 @@ eval-expression
(eval-expression-get-print-arguments current-prefix-arg)))
(if (null eval-expression-debug-on-error)
- (push (eval exp lexical-binding) values)
+ (push (eval exp t) values)
(let ((old-value (make-symbol "t")) new-value)
;; Bind debug-on-error to something unique so that we can
;; detect when evalled code changes it.
(let ((debug-on-error old-value))
- (push (eval (macroexpand-all exp) lexical-binding) values)
+ (push (eval (macroexpand-all exp) t) values)
(setq new-value debug-on-error))
;; If evalled code has changed the value of debug-on-error,
;; propagate that change to the global binding.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Thu, 11 Jan 2018 21:00:02 GMT)
Full text and
rfc822 format available.
Message #8 received at 30078 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> IRO.UMontreal.CA> writes:
> I think we should slowly move towards making lexical-binding the default
> and we could start by making M-: always use lexical binding.
> WDYT?
Why not?
But maybe we should keep this consistent with C-x C-e in *scratch* to
avoid confusion (a la "why do the evaluation results differ?"),
i.e. enable lexical-binding in *scratch* at the same time?
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 14:55:02 GMT)
Full text and
rfc822 format available.
Message #11 received at 30078 <at> debbugs.gnu.org (full text, mbox):
>> I think we should slowly move towards making lexical-binding the default
>> and we could start by making M-: always use lexical binding.
>> WDYT?
> Why not?
> But maybe we should keep this consistent with C-x C-e in *scratch* to
> avoid confusion (a la "why do the evaluation results differ?"),
> i.e. enable lexical-binding in *scratch* at the same time?
Good idea.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 16:09:01 GMT)
Full text and
rfc822 format available.
Message #14 received at 30078 <at> debbugs.gnu.org (full text, mbox):
>>> I think we should slowly move towards making lexical-binding the default
>>> and we could start by making M-: always use lexical binding.
>>> WDYT?
>> Why not?
>> But maybe we should keep this consistent with C-x C-e in *scratch* to
>> avoid confusion (a la "why do the evaluation results differ?"),
>> i.e. enable lexical-binding in *scratch* at the same time?
> Good idea.
I figured M-x ielm would qualify as well.
How 'bout this patch, then?
Stefan
diff --git a/etc/NEWS b/etc/NEWS
index f6f36dfc85..d7e84eca7f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -52,6 +52,10 @@ to reduce differences between developer and production builds.
* Changes in Emacs 27.1
+** Lexical binding is now used when evaluating interactive Elisp forms
+More specifically, lexical-binding is used for M-:, M-x ielm, as well
+as in the *scratch* buffer.
+
---
** The new option 'tooltip-resize-echo-area' avoids truncating tooltip text
on GUI frames when tooltips are displayed in the echo area. Instead,
diff --git a/lisp/ielm.el b/lisp/ielm.el
index fb285e80f6..cad1bded4f 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -408,8 +408,7 @@ ielm-eval-input
(setf standard-output new-standard-output))
(kill-buffer (current-buffer))
(set-buffer wbuf)
- (setq result
- (eval form lexical-binding))
+ (setq result (eval form t))
(setq wbuf (current-buffer))
(setq
ielm-temp-buffer
diff --git a/lisp/server.el b/lisp/server.el
index ac0d701851..918197ab44 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -1294,7 +1294,7 @@ server-execute
((functionp initial-buffer-choice)
(funcall initial-buffer-choice)))))
(switch-to-buffer
- (if (buffer-live-p buf) buf (get-buffer-create "*scratch*"))
+ (if (buffer-live-p buf) buf (startup--get-buffer-create-scratch))
'norecord)))
;; Delete the client if necessary.
diff --git a/lisp/simple.el b/lisp/simple.el
index 87e0b23377..e2d3cd1505 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1555,12 +1555,12 @@ eval-expression
(eval-expression-get-print-arguments current-prefix-arg)))
(if (null eval-expression-debug-on-error)
- (push (eval exp lexical-binding) values)
+ (push (eval exp t) values)
(let ((old-value (make-symbol "t")) new-value)
;; Bind debug-on-error to something unique so that we can
;; detect when evalled code changes it.
(let ((debug-on-error old-value))
- (push (eval (macroexpand-all exp) lexical-binding) values)
+ (push (eval (macroexpand-all exp) t) values)
(setq new-value debug-on-error))
;; If evalled code has changed the value of debug-on-error,
;; propagate that change to the global binding.
diff --git a/lisp/startup.el b/lisp/startup.el
index 688ea84b7b..f3c0c7b100 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -2095,7 +2095,7 @@ normal-no-mouse-startup-screen
(insert "\t\t")
(insert-button "Open *scratch* buffer"
'action (lambda (_button) (switch-to-buffer
- (get-buffer-create "*scratch*")))
+ (startup--get-buffer-create-scratch)))
'follow-link t)
(insert "\n")
(insert "\n" (emacs-version) "\n" emacs-copyright "\n")
@@ -2221,6 +2221,12 @@ display-about-screen
(defalias 'about-emacs 'display-about-screen)
(defalias 'display-splash-screen 'display-startup-screen)
+(defun startup--get-buffer-create-scratch ()
+ (with-current-buffer (get-buffer-create "*scratch*")
+ (set-buffer-major-mode (current-buffer))
+ (setq-local lexical-binding t)
+ (current-buffer)))
+
(defun command-line-1 (args-left)
"A subroutine of `command-line'."
(display-startup-echo-area-message)
@@ -2485,7 +2491,7 @@ command-line-1
(when (eq initial-buffer-choice t)
;; When `initial-buffer-choice' equals t make sure that *scratch*
;; exists.
- (get-buffer-create "*scratch*"))
+ (startup--get-buffer-create-scratch))
;; If *scratch* exists and is empty, insert initial-scratch-message.
;; Do this before switching to *scratch* below to handle bug#9605.
@@ -2504,7 +2510,7 @@ command-line-1
((functionp initial-buffer-choice)
(funcall initial-buffer-choice))
((eq initial-buffer-choice t)
- (get-buffer-create "*scratch*"))
+ (startup--get-buffer-create-scratch))
(t
(error "initial-buffer-choice must be a string, a function, or t.")))))
(unless (buffer-live-p buf)
diff --git a/lisp/window.el b/lisp/window.el
index d7fdceb205..7f89c87af1 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4578,7 +4578,7 @@ last-buffer
(or (get-next-valid-buffer (nreverse (buffer-list frame))
buffer visible-ok frame)
(get-buffer "*scratch*")
- (let ((scratch (get-buffer-create "*scratch*")))
+ (let ((scratch (startup--get-buffer-create-scratch)))
(set-buffer-major-mode scratch)
scratch)))
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 16:54:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 30078 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier wrote:
> How 'bout this patch, then?
You forgot all the documentation updates. :)
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 17:24:02 GMT)
Full text and
rfc822 format available.
Message #20 received at 30078 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> IRO.UMontreal.CA> writes:
> (defun command-line-1 (args-left)
> "A subroutine of `command-line'."
> (display-startup-echo-area-message)
> @@ -2485,7 +2491,7 @@ command-line-1
> (when (eq initial-buffer-choice t)
> ;; When `initial-buffer-choice' equals t make sure that *scratch*
> ;; exists.
> - (get-buffer-create "*scratch*"))
> + (startup--get-buffer-create-scratch))
>
> ;; If *scratch* exists and is empty, insert initial-scratch-message.
> ;; Do this before switching to *scratch* below to handle bug#9605.
Don't you also want to change this occurrence in `command-line'?
#+begin_src emacs-lisp
;; If *scratch* exists and init file didn't change its mode, initialize it.
(if (get-buffer "*scratch*")
(with-current-buffer "*scratch*"
(if (eq major-mode 'fundamental-mode)
(funcall initial-major-mode))))
#+end_src
So far, lexical-binding in *scratch* is nil with emacs -Q with your
patch.
Maybe also check that evaluating the expression `lexical-binding'
returns a result that is consistent with the evaluation behavior. In
particular, evaluating lexical-binding in M-x ielm RET still gives nil -
that's confusing.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 18:35:02 GMT)
Full text and
rfc822 format available.
Message #23 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
> Date: Fri, 12 Jan 2018 11:12:23 -0500
> Cc: 30078 <at> debbugs.gnu.org
>
> +** Lexical binding is now used when evaluating interactive Elisp forms
> +More specifically, lexical-binding is used for M-:, M-x ielm, as well
> +as in the *scratch* buffer.
Please, not in *scratch*. Setting variables and then evaluating forms
that use them is very useful there.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 18:44:02 GMT)
Full text and
rfc822 format available.
Message #26 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> Don't you also want to change this occurrence in `command-line'?
>
> #+begin_src emacs-lisp
> ;; If *scratch* exists and init file didn't change its mode, initialize it.
> (if (get-buffer "*scratch*")
> (with-current-buffer "*scratch*"
> (if (eq major-mode 'fundamental-mode)
> (funcall initial-major-mode))))
> #+end_src
Ah, so that's where it is, thanks.
> So far, lexical-binding in *scratch* is nil with emacs -Q with your
> patch.
That's what I was seeing as well, indeed :-(
> Maybe also check that evaluating the expression `lexical-binding'
> returns a result that is consistent with the evaluation behavior.
I already know that the check will fail. Is it important?
In general the value of the variable lexical-binding during evaluation
of the code is not directly related to whether the code is evaluated
using lexical rules or not. Within macros, Emacs tries to make sure
that lexical-binding reflects whether the code returned by the macro
will use lexical scoping or not (so that the macro can adjust the code
it generates accordingly), but other than that, the two are
largely independent (which is why (setq lexical-binding t) is not the
right way to enable lexical scoping in a file).
> In particular, evaluating lexical-binding in M-x ielm RET still gives
> nil - that's confusing.
Right (well, it doesn't always give you nil: it depends on the value of
lexical-binding in the buffer currently selected to evaluate the IELM
expressions).
But this discrepancy also shows up in various other contexts. Eg.:
;; -*- lexical-binding:t -*-
(defun my-test ()
(interactive)
(message "%S" lexical-binding))
will give you a lexically scoped command which will tell you the value
of lexical-binding at the time&place you run the command, which will
sometimes be t and sometimes not.
I'm not sure we should try to encourage the user to think a piece of
code can check the value of `lexical-binding` to know if it's being
evaluated using lexical scoping rules.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 18:46:01 GMT)
Full text and
rfc822 format available.
Message #29 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> Please, not in *scratch*. Setting variables and then evaluating forms
> that use them is very useful there.
I'm not sure how the two sentences are connected:
Setting lexical-binding to t in *scratch* won't prevent setting
variables and evaluating forms that use them.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 18:57:02 GMT)
Full text and
rfc822 format available.
Message #32 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
> Cc: michael_heerdegen <at> web.de, 30078 <at> debbugs.gnu.org
> Date: Fri, 12 Jan 2018 13:49:00 -0500
>
> > Please, not in *scratch*. Setting variables and then evaluating forms
> > that use them is very useful there.
>
> I'm not sure how the two sentences are connected:
> Setting lexical-binding to t in *scratch* won't prevent setting
> variables and evaluating forms that use them.
For some value of "prevent", surely? Dynamically-bound variables will
no longer work as they did before, right?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 19:03:02 GMT)
Full text and
rfc822 format available.
Message #35 received at 30078 <at> debbugs.gnu.org (full text, mbox):
>> > Please, not in *scratch*. Setting variables and then evaluating forms
>> > that use them is very useful there.
>> I'm not sure how the two sentences are connected:
>> Setting lexical-binding to t in *scratch* won't prevent setting
>> variables and evaluating forms that use them.
> For some value of "prevent", surely? Dynamically-bound variables will
> no longer work as they did before, right?
No, they'll work pretty much as before.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 19:36:02 GMT)
Full text and
rfc822 format available.
Message #38 received at 30078 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> IRO.UMontreal.CA> writes:
> I'm not sure we should try to encourage the user to think a piece of
> code can check the value of `lexical-binding` to know if it's being
> evaluated using lexical scoping rules.
I'm not sure, too. But aren't *scratch* and *ielm* special? These are
the current buffers when code is evaluated, but they are also some kind
of source-code buffer at the same time. In source code file buffers,
M-x lexical-binding RET gives you the right answer about how the code in
this buffers is interpreted.
I think we should be careful - maybe new users are trying to learn Elisp
with the help of *ielm*.
With your patch, you get
ELISP> (let ((x 1)) (lambda () x))
(closure
((x . 1)
t)
nil x)
but if you put point after the input expression and hit C-x C-e you
suddenly get
(lambda nil x)
People who are actually learning Elisp will not make any sense out of
this, I think.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 20:04:04 GMT)
Full text and
rfc822 format available.
Message #41 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
> Cc: michael_heerdegen <at> web.de, 30078 <at> debbugs.gnu.org
> Date: Fri, 12 Jan 2018 14:06:41 -0500
>
> >> > Please, not in *scratch*. Setting variables and then evaluating forms
> >> > that use them is very useful there.
> >> I'm not sure how the two sentences are connected:
> >> Setting lexical-binding to t in *scratch* won't prevent setting
> >> variables and evaluating forms that use them.
> > For some value of "prevent", surely? Dynamically-bound variables will
> > no longer work as they did before, right?
>
> No, they'll work pretty much as before.
Then you are saying that turning on lexical-binding in *scratch* will
change nothing at all? I very much doubt that, and my witness are all
those packages that broke due to lexical-binding and needed minor
fixes.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 20:34:02 GMT)
Full text and
rfc822 format available.
Message #44 received at 30078 <at> debbugs.gnu.org (full text, mbox):
On Fri, Jan 12, 2018 at 3:03 PM, Eli Zaretskii <eliz <at> gnu.org> wrote:
>> From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
>> Cc: michael_heerdegen <at> web.de, 30078 <at> debbugs.gnu.org
>> Date: Fri, 12 Jan 2018 14:06:41 -0500
>>
>> >> > Please, not in *scratch*. Setting variables and then evaluating forms
>> >> > that use them is very useful there.
>> >> I'm not sure how the two sentences are connected:
>> >> Setting lexical-binding to t in *scratch* won't prevent setting
>> >> variables and evaluating forms that use them.
>> > For some value of "prevent", surely? Dynamically-bound variables will
>> > no longer work as they did before, right?
>>
>> No, they'll work pretty much as before.
>
> Then you are saying that turning on lexical-binding in *scratch* will
> change nothing at all? I very much doubt that, and my witness are all
> those packages that broke due to lexical-binding and needed minor
> fixes.
Top-level `setq's would be unaffected (because the lexical environment
at the top level is empty). Lexical binding only changes what `let'
does, for undeclared variables.
(okay, not *just* `let', it also affects `lambda')
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 20:56:02 GMT)
Full text and
rfc822 format available.
Message #47 received at 30078 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
> Then you are saying that turning on lexical-binding in *scratch* will
> change nothing at all? I very much doubt that, and my witness are
> all those packages that broke due to lexical-binding and needed minor
> fixes.
I do what has been proposed for months. I liked it.
What are we doing with scratch?
(1) Setting global variables, defining small functions and such simple
stuff. lexical-binding doesn't make a big difference here.
(2) Re-evaluate parts of the source code, often with small
modifications, for testing and debugging. Since more and more packages
make active use of lexical-binding, this is actually broken currently!
Re-evaluating parts of source code in scratch can currently break Emacs.
(3) I often posted some code examples in emacs-help which made use of
lexical-binding. People pasted it into scratch and it didn't work.
It's currently even not trivial to evaluate such examples with
lexical-binding on.
OTOH, there is not too much code that really relies on dynamical binding
mode. And very often, such code is just written in a bad style (missing
`defvar's etc.).
In summary, I think the advantages clearly prevail.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 21:06:01 GMT)
Full text and
rfc822 format available.
Message #50 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> From: Michael Heerdegen <michael_heerdegen <at> web.de>
> Cc: Stefan Monnier <monnier <at> IRO.UMontreal.CA>, 30078 <at> debbugs.gnu.org
> Date: Fri, 12 Jan 2018 21:55:25 +0100
>
> What are we doing with scratch?
>
> (1) Setting global variables, defining small functions and such simple
> stuff. lexical-binding doesn't make a big difference here.
We need to discuss the differences whether they are big or not.
> (2) Re-evaluate parts of the source code, often with small
> modifications, for testing and debugging. Since more and more packages
> make active use of lexical-binding, this is actually broken currently!
> Re-evaluating parts of source code in scratch can currently break Emacs.
You are describing a mistake. People make mistakes all the time, and
will continue making mistakes whatever we do. That shouldn't be a
basis for our decisions.
> (3) I often posted some code examples in emacs-help which made use of
> lexical-binding. People pasted it into scratch and it didn't work.
> It's currently even not trivial to evaluate such examples with
> lexical-binding on.
Another mistake. I don't see why this should be of any importance for
the decision at hand.
> OTOH, there is not too much code that really relies on dynamical binding
> mode. And very often, such code is just written in a bad style (missing
> `defvar's etc.).
That's your opinion. I happen not to share it.
> In summary, I think the advantages clearly prevail.
I actually didn't yet see any advantages mentioned, and the above
aren't, IMO. Lexical-binding is just a feature, albeit an important
one. It doesn't have to be introduced into every possible corner of
Emacs, not without a good reason.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Fri, 12 Jan 2018 21:12:01 GMT)
Full text and
rfc822 format available.
Message #53 received at 30078 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
> I actually didn't yet see any advantages mentioned, and the above
> aren't, IMO. Lexical-binding is just a feature, albeit an important
> one. It doesn't have to be introduced into every possible corner of
> Emacs, not without a good reason.
Ah, so you doubt that lexical-binding once should just be the default.
Then I think we should discuss about this goal.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 17:51:01 GMT)
Full text and
rfc822 format available.
Message #56 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> On 12. Jan 2018, at 22:11, Michael Heerdegen <michael_heerdegen <at> web.de> wrote:
>
> Ah, so you doubt that lexical-binding once should just be the default.
> Then I think we should discuss about this goal.
Here are a few possible pros of lexical binding:
1) Make Elisp more approachable to newcomers. Lexical binding is the default in most programming languages and thus more people are familiar with it. This makes it easier for people to understand existing code since they don‘t have to get used to implicit dynamic binding first, which the code may take advantage of.
2) Make existing code more maintainable. I was involved in porting the package emacs-eclim to lexical binding. The process shed light on some very dark parts of the codebase nobody had touched in a while since they were written in very bad style and thus hard to understand. Using lexical binding forced us to simplify those parts.
3) This is a minor one: I‘ve heard that lexical binding allows for more optimizations. I don‘t know to which extend this actually happens and whether it is noticeable to the user.
I believe 1) and 2) will significantly help improving the general quality of Elisp code and thus of Emacs in general.
Here‘s the big con:
If lexical binding should become the default one day, you would have to give everyone a reasonable amount of time (multiple years?) to adapt for it and port their code or set lexical binding to nil in their files.
One idea would be to make elisp-mode somehow encourage users to enable lexical binding in the files they are editing. Any ideas how this can be done without annoying users? Ideas:
- Prompting every time elisp-mode is enabled in a file that does not have a lexical binding header.
- I know that certain functions insert a apropriate copyright notice into el-files, do / can those also set lexical binding to t?
Best regards,
Luis
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 17:59:02 GMT)
Full text and
rfc822 format available.
Message #59 received at 30078 <at> debbugs.gnu.org (full text, mbox):
>> I'm not sure we should try to encourage the user to think a piece of
>> code can check the value of `lexical-binding` to know if it's being
>> evaluated using lexical scoping rules.
> I'm not sure, too. But aren't *scratch* and *ielm* special? These are
> the current buffers when code is evaluated,
For *scratch* yes, but for *ielm* that's not the case: the code is
evaluated in the `ielm-working-buffer` (whose name normally appears in
the mode-line after "IELM").
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 18:07:01 GMT)
Full text and
rfc822 format available.
Message #62 received at 30078 <at> debbugs.gnu.org (full text, mbox):
>> No, they'll work pretty much as before.
> Then you are saying that turning on lexical-binding in *scratch* will
> change nothing at all?
Not nothing at all, but the two languages are *very* similar and the
differences rarely show up in a single expression.
My gut feeling is that the main risk to bump into an undesirable
behavior is something like
(let ((foopkg-var t))
(foopkg-fun arg1 arg2))
where foopkg is not yet loaded and foopkg-fun is autoloaded: Emacs will
only be told that `foopkg-var` is a dynamic-variable once the
`foopkg-fun` call causes `foopkg` to be loaded, so Emacs will mistakenly
use lexical scoping for the let binding because at that it still knows
nothing about `foopkg-var`.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 18:20:02 GMT)
Full text and
rfc822 format available.
Message #65 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> Lexical-binding is just a feature, albeit an important one.
> It doesn't have to be introduced into every possible corner of Emacs,
> not without a good reason.
lexbind-Elisp and dynbind-Elisp are fundamentally two different
languages. They are so similar that we don't think of it in those
terms, but having those 2 introduces complexity (including for the users
occasionally). And actually the fact they're so similar sometimes makes
the problem worse because most people don't realize that they have to
pay attention to it or how to know which language is used when.
I very much hope to see Emacs shed its dynbind-Elisp support at some
point, tho it still seems to be a pretty distant future and I'm not even
sure how we'll get to that point.
bug#30078 is about making another step in this direction.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 19:35:02 GMT)
Full text and
rfc822 format available.
Message #68 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
> Cc: Michael Heerdegen <michael_heerdegen <at> web.de>, 30078 <at> debbugs.gnu.org
> Date: Sat, 13 Jan 2018 13:19:52 -0500
>
> I very much hope to see Emacs shed its dynbind-Elisp support at some
> point, tho it still seems to be a pretty distant future and I'm not even
> sure how we'll get to that point.
It's quite clear that these are your views, but going in that
direction should be an explicit project-wide decision, widely agreed
and accepted by main project contributors. Doing it one subtle step
at a time is not the right way, IMO. If and when such a decision is
made, we would not need to have these discussions, we could simply go
lexical-bind as quickly as it's practical.
My comments in this thread are largely because I feel uneasy about
this undeclared policy for quite some time.
For the record, I have nothing against making lexical-binding the
default, if that's what everybody wants.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 19:38:01 GMT)
Full text and
rfc822 format available.
Message #71 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
> Cc: michael_heerdegen <at> web.de, 30078 <at> debbugs.gnu.org
> Date: Sat, 13 Jan 2018 13:05:58 -0500
>
> (let ((foopkg-var t))
> (foopkg-fun arg1 arg2))
>
> where foopkg is not yet loaded and foopkg-fun is autoloaded: Emacs will
> only be told that `foopkg-var` is a dynamic-variable once the
> `foopkg-fun` call causes `foopkg` to be loaded, so Emacs will mistakenly
> use lexical scoping for the let binding because at that it still knows
> nothing about `foopkg-var`.
That indeed could be a confusing situation, perhaps we should have a
special form for it, to avoid the confusing/incorrect/unexpected
results.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 19:50:02 GMT)
Full text and
rfc822 format available.
Message #74 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> From: Luis Gerhorst <privat <at> luisgerhorst.de>
> Date: Sat, 13 Jan 2018 18:50:36 +0100
> Cc: Eli Zaretskii <eliz <at> gnu.org>, monnier <at> IRO.UMontreal.CA,
> 30078 <at> debbugs.gnu.org
>
> 1) Make Elisp more approachable to newcomers. Lexical binding is the default in most programming languages and thus more people are familiar with it. This makes it easier for people to understand existing code since they don‘t have to get used to implicit dynamic binding first, which the code may take advantage of.
Do we know for a fact that most users who extend Emacs by writing
their own Lisp have background in Lisps and other similar languages
where lexical binding is the default? If not, dynamic binding might
be easier to grasp for the newcomers.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 20:20:01 GMT)
Full text and
rfc822 format available.
Message #77 received at 30078 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii writes:
> Do we know for a fact that most users who extend Emacs by writing
> their own Lisp have background in Lisps and other similar languages
> where lexical binding is the default? If not, dynamic binding might
> be easier to grasp for the newcomers.
I wouldn't say we know it for a fact, but I would say we can be pretty
sure about it.
I think nobody would deny that imperative languages, which mostly use
lexical binding, are much more popular (e.g. google the 10 most popular
programming languages).
You may argue that Emacs users have another background but if you go to
https://github.com/topics/emacs and look at the contributors of an
arbitrary project you can be almost certain they have at least one
imperative language in ther portfolio (most I've looked at only have
imperative languages and Emacs Lisp projects).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 21:59:01 GMT)
Full text and
rfc822 format available.
Message #80 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> It's quite clear that these are your views, but going in that
> direction should be an explicit project-wide decision, widely agreed
> and accepted by main project contributors.
Of course.
> If and when such a decision is made, we would not need to have these
> discussions, we could simply go lexical-bind as quickly as
> it's practical.
That's what I think I'm doing.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sat, 13 Jan 2018 23:19:02 GMT)
Full text and
rfc822 format available.
Message #83 received at 30078 <at> debbugs.gnu.org (full text, mbox):
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
We could introduce a warning for any Lisp file that fails to specify
lexical vs dynamic. After a few years, we could assume that all files
specify it, so we could change the default.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sun, 14 Jan 2018 02:08:02 GMT)
Full text and
rfc822 format available.
Message #86 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> lexbind-Elisp and dynbind-Elisp are fundamentally two different
> languages.
If you want to argue that then Lisp itself is fundamentally
several languages. (Yes, even Lisp 1.5, sans CLOS and all
the rest.)
Nothing says that a single language cannot "fundamentally"
have more than one kind of binding/scoping.
> They are so similar that we don't think of it in those
> terms, but having those 2 introduces complexity (including for the users
> occasionally). And actually the fact they're so similar sometimes makes
> the problem worse because most people don't realize that they have to
> pay attention to it or how to know which language is used when.
There are plenty of things that one needs to pay attention
to in Lisp. List-structure, for one. Lisp is not Haskell.
Yes, Lisp can be complex, for both users and implementors.
> I very much hope to see Emacs shed its dynbind-Elisp support at some
> point, tho it still seems to be a pretty distant future and I'm not even
> sure how we'll get to that point.
I very much hope _not_.
Lexical and dynamic binding each have their place in Lisp,
especially in Emacs Lisp. RMS underlined the importance
of dynamic binding for Emacs. That argument remains as
potent and relevant today as when he wrote it.
http://www.gnu.org/software/emacs/emacs-paper.html#SEC18
Lexical and dynamic binding have coexisted fine in Common
Lisp for almost 40 years now.
And lexical binding is the default in Common Lisp. That
would be fine for Emacs Lisp too someday. I have no
objection to a move toward that, in principle.
It was a definite plus to add lexical binding to Emacs.
Thank you very much for that. Bravo. (And a vacuous
`defvar' is not a bad way to declare a special/dynamic
variable.)
On the other hand, it would be a definite impairment to
remove dynamic binding from Emacs Lisp. No thank you.
> bug#30078 is about making another step in this direction.
If that's all bug#30078 is about then don't do it.
(But I hope that's not all it's about.)
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Sun, 14 Jan 2018 06:00:02 GMT)
Full text and
rfc822 format available.
Message #89 received at 30078 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
>> From: Luis Gerhorst <privat <at> luisgerhorst.de>
>> Date: Sat, 13 Jan 2018 18:50:36 +0100
>> Cc: Eli Zaretskii <eliz <at> gnu.org>, monnier <at> IRO.UMontreal.CA,
>> 30078 <at> debbugs.gnu.org
>>
>> 1) Make Elisp more approachable to newcomers. Lexical binding is the default
>> in most programming languages and thus more people are familiar with it. This
>> makes it easier for people to understand existing code since they don‘t have
>> to get used to implicit dynamic binding first, which the code may take
>> advantage of.
>
> Do we know for a fact that most users who extend Emacs by writing
> their own Lisp have background in Lisps and other similar languages
> where lexical binding is the default? If not, dynamic binding might
> be easier to grasp for the newcomers.
I learned Emacs Lisp by learning Common Lisp first when I set out to
learn it. Prior to that, I had been programming in languages that have
lexical scoping as the primary scope mechanism. I personally do not know
of non-Lisp languages that have variables that work like dynamic
variables do.
And of course I can't comment from the perspective from a newcommer any
more, but I'd be of the mind that entirely dynamic binding would be
/less/ easy to grasp, because it does things that I personally find
non-intuitive in certain circumstances. I have programmer friends that
use Emacs but don't do their own Emacs Lisp, and I would hazard a guess
that dynamic bindings would be unintuitive when they differ from lexical
bindings in behavior.
IMO, the fact that dynamic bindings happen to do the same thing as
lexical bindings is the reason the whole thing isn't nearly as confusing
as it could be.
That's not to say that dynamic bindings are bad - far from it. Dynamic
bindings are really useful. But I think that the potentially confusing
behavior should be opt-in, not opt-out.
--
~Robert Cochran
GPG Fingerprint - BD0C 5F8B 381C 64F0 F3CE E7B9 EC9A 872C 41B2 77C2
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Mon, 15 Jan 2018 02:36:01 GMT)
Full text and
rfc822 format available.
Message #92 received at 30078 <at> debbugs.gnu.org (full text, mbox):
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> Lexical and dynamic binding each have their place in Lisp,
> especially in Emacs Lisp. RMS underlined the importance
> of dynamic binding for Emacs.
Emacs must have dynamic binding, but that doesn't mean it
needs to have a mode where dynamic binding is the default.
It can be limited to the variables declared to be dynamic.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Mon, 19 Mar 2018 19:33:02 GMT)
Full text and
rfc822 format available.
Message #95 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> I figured M-x ielm would qualify as well.
Seeing how forcing lexical-binding within *ielm* raised some objections,
I've changed my patch so it only sets lexical-binding in the *ielm*
buffer but the evaluation mode will still depend on the
lexical-binding setting in ielm-working-buffer (so evaluating
`lexical-binding' will again return a value which indicates whether
expressions are evaluated using lexical-binding).
New patch below.
There were some issues regarding the general long term goal of
standardizing on lexical-binding. So I'm restarting this discussion
below.
I wrote:
> > I very much hope to see Emacs shed its dynbind-Elisp support at some
> > point, tho it still seems to be a pretty distant future and I'm not even
> > sure how we'll get to that point.
To which Eli replied:
> It's quite clear that these are your views, but going in that
> direction should be an explicit project-wide decision, widely agreed
> and accepted by main project contributors. Doing it one subtle step
> at a time is not the right way, IMO. If and when such a decision is
> made, we would not need to have these discussions, we could simply go
> lexical-bind as quickly as it's practical.
Fully agreed. FWIW, this is the decision I took when I added
lexical-binding into Emacs-24.1. I had no idea that someone might like
to disagree: the lexbind-Elisp language is a strict superset of the
dynbind-Elisp language and for that reason I don't see any reason other
than backward compatibility to keep dynbind-Elisp.
I'm not trying to fool people by "doing it one subtle step at a time",
I'm only trying to make this switch as painless as possible. I don't
yet have a plan for how we'll get rid of dynbind-Elisp and I'm sure
it'll take many years and several more steps, some of them less subtle
than others. Some of the steps I could imagine introducing in the not
too distant future:
- finish converting all Emacs's .el files to use lexical-binding:t.
- emit a warning when opening an Elisp file which doesn't specify
`lexical-binding:t' in its local vars.
- emit a warning when `eval` is called without a nil 2nd arg.
AFAICT by looking at packages on github, lexical-binding is very
popular, despite the fact that it limits packages to Emacs≥24 and
requires explicitly adding a magic cookie on the first line. Also I've
only gotten positive feedback so far about it (more specifically, the
above paragraph of yours is the most negative feedback I've hard about
lexical-binding so far).
Eli also wrote:
> Do we know for a fact that most users who extend Emacs by writing
> their own Lisp have background in Lisps and other similar languages
> where lexical binding is the default? If not, dynamic binding might
> be easier to grasp for the newcomers.
Lexical scoping is not specific to Lisp or similar languages: it's the
scoping supported by virtually all programming languages such as
Javascript, Pascal, Fortran, Smalltalk, C, Python, Rust, Java, C#,
Clojure, Ruby, Perl, ... The vast majority of those *only* supports
lexical scoping.
It's dynamic binding which is the odd one out: I can't think of too many
languages supporting dynamic scoping other than Scheme, Common-Lisp,
Elisp, Logo, sh, and Perl (and maybe Awk tho the doc I can find doesn't make
it clear), most of which also support lexical scoping (the only
exceptions I know are Logo, sh, and maybe Awk).
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Mon, 19 Mar 2018 19:35:01 GMT)
Full text and
rfc822 format available.
Message #98 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> New patch below.
Of course, I got side-tracked and forgot to include the patch.
Here it is,
Stefan
diff --git a/etc/NEWS b/etc/NEWS
index 99f3f27486..2d985aab9e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -71,6 +71,10 @@ moved to the early init file (see above).
* Changes in Emacs 27.1
+** Lexical binding is now used when evaluating interactive Elisp forms
+More specifically, lexical-binding is now used for M-:, --eval, as well
+as in the *scratch* and *ielm* buffers.
+
---
** The new option 'tooltip-resize-echo-area' avoids truncating tooltip text
on GUI frames when tooltips are displayed in the echo area. Instead,
diff --git a/lisp/ielm.el b/lisp/ielm.el
index 59e333f19c..73cf37efbc 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -559,10 +559,11 @@ inferior-emacs-lisp-mode
;; Useful for `hs-minor-mode'.
(setq-local comment-start ";")
(setq-local comment-use-syntax t)
+ (setq-local lexical-binding t)
- (set (make-local-variable 'indent-line-function) 'ielm-indent-line)
+ (set (make-local-variable 'indent-line-function) #'ielm-indent-line)
(set (make-local-variable 'ielm-working-buffer) (current-buffer))
- (set (make-local-variable 'fill-paragraph-function) 'lisp-fill-paragraph)
+ (set (make-local-variable 'fill-paragraph-function) #'lisp-fill-paragraph)
;; Value holders
(set (make-local-variable '*) nil)
diff --git a/lisp/server.el b/lisp/server.el
index ff03cbe622..a8a82922f5 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -793,7 +793,7 @@ server-eval-and-print
;; intended it to interrupt us rather than interrupt whatever Emacs
;; was doing before it started handling the process filter.
;; Hence `with-local-quit' (bug#6585).
- (let ((v (with-local-quit (eval (car (read-from-string expr))))))
+ (let ((v (with-local-quit (eval (car (read-from-string expr)) t))))
(when proc
(with-temp-buffer
(let ((standard-output (current-buffer)))
@@ -1315,7 +1315,7 @@ server-execute
(find-file-noselect initial-buffer-choice))
((functionp initial-buffer-choice)
(funcall initial-buffer-choice)))))
- (if (buffer-live-p buf) buf (get-buffer-create "*scratch*")))))
+ (if (buffer-live-p buf) buf (startup--get-buffer-create-scratch)))))
;; Set current buffer so that newly created tty frames
;; show the correct buffer initially.
(frame (with-current-buffer (or (car buffers)
diff --git a/lisp/simple.el b/lisp/simple.el
index fa93cf87c7..f578efb7cb 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1579,12 +1579,12 @@ eval-expression
(eval-expression-get-print-arguments current-prefix-arg)))
(if (null eval-expression-debug-on-error)
- (push (eval exp lexical-binding) values)
+ (push (eval exp t) values)
(let ((old-value (make-symbol "t")) new-value)
;; Bind debug-on-error to something unique so that we can
;; detect when evalled code changes it.
(let ((debug-on-error old-value))
- (push (eval (macroexpand-all exp) lexical-binding) values)
+ (push (eval (macroexpand-all exp) t) values)
(setq new-value debug-on-error))
;; If evalled code has changed the value of debug-on-error,
;; propagate that change to the global binding.
diff --git a/lisp/startup.el b/lisp/startup.el
index 2669342eda..77d6232924 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -1357,7 +1357,8 @@ command-line
(if (get-buffer "*scratch*")
(with-current-buffer "*scratch*"
(if (eq major-mode 'fundamental-mode)
- (funcall initial-major-mode))))
+ (funcall initial-major-mode))
+ (setq-local lexical-binding t)))
;; Load library for our terminal type.
;; User init file can set term-file-prefix to nil to prevent this.
@@ -2103,7 +2104,7 @@ normal-no-mouse-startup-screen
(insert "\t\t")
(insert-button "Open *scratch* buffer"
'action (lambda (_button) (switch-to-buffer
- (get-buffer-create "*scratch*")))
+ (startup--get-buffer-create-scratch)))
'follow-link t)
(insert "\n")
(insert "\n" (emacs-version) "\n" emacs-copyright "\n")
@@ -2229,6 +2230,13 @@ display-about-screen
(defalias 'about-emacs 'display-about-screen)
(defalias 'display-splash-screen 'display-startup-screen)
+(defun startup--get-buffer-create-scratch ()
+ (or (get-buffer "*scratch*")
+ (with-current-buffer (get-buffer-create "*scratch*")
+ (set-buffer-major-mode (current-buffer))
+ (setq-local lexical-binding t)
+ (current-buffer))))
+
(defun command-line-1 (args-left)
"A subroutine of `command-line'."
(display-startup-echo-area-message)
@@ -2378,7 +2386,7 @@ command-line-1
(unless (= end (length str-expr))
(error "Trailing garbage following expression: %s"
(substring str-expr end)))
- (eval expr)))
+ (eval expr t)))
((member argi '("-L" "-directory"))
;; -L :/foo adds /foo to the _end_ of load-path.
@@ -2493,7 +2501,7 @@ command-line-1
(when (eq initial-buffer-choice t)
;; When `initial-buffer-choice' equals t make sure that *scratch*
;; exists.
- (get-buffer-create "*scratch*"))
+ (startup--get-buffer-create-scratch))
;; If *scratch* exists and is empty, insert initial-scratch-message.
;; Do this before switching to *scratch* below to handle bug#9605.
@@ -2512,7 +2520,7 @@ command-line-1
((functionp initial-buffer-choice)
(funcall initial-buffer-choice))
((eq initial-buffer-choice t)
- (get-buffer-create "*scratch*"))
+ (startup--get-buffer-create-scratch))
(t
(error "initial-buffer-choice must be a string, a function, or t.")))))
(unless (buffer-live-p buf)
diff --git a/lisp/window.el b/lisp/window.el
index 8c5e441e4b..3f475ce8ae 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4578,7 +4578,7 @@ last-buffer
(or (get-next-valid-buffer (nreverse (buffer-list frame))
buffer visible-ok frame)
(get-buffer "*scratch*")
- (let ((scratch (get-buffer-create "*scratch*")))
+ (let ((scratch (startup--get-buffer-create-scratch)))
(set-buffer-major-mode scratch)
scratch)))
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Mon, 19 Mar 2018 20:11:01 GMT)
Full text and
rfc822 format available.
Message #101 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
> Date: Mon, 19 Mar 2018 15:32:23 -0400
> Cc: 30078 <at> debbugs.gnu.org
>
> lexbind-Elisp language is a strict superset of the
> dynbind-Elisp language and for that reason I don't see any reason other
> than backward compatibility to keep dynbind-Elisp.
>
> I'm not trying to fool people by "doing it one subtle step at a time",
> I'm only trying to make this switch as painless as possible. I don't
> yet have a plan for how we'll get rid of dynbind-Elisp and I'm sure
> it'll take many years and several more steps, some of them less subtle
> than others. Some of the steps I could imagine introducing in the not
> too distant future:
> - finish converting all Emacs's .el files to use lexical-binding:t.
> - emit a warning when opening an Elisp file which doesn't specify
> `lexical-binding:t' in its local vars.
> - emit a warning when `eval` is called without a nil 2nd arg.
Really? Get rid of dynamic binding in ELisp? Why is that a good
idea? It would mean old code will not run in Emacs for no good
reason.
> It's dynamic binding which is the odd one out
Not for me, it isn't. Maybe that means _I_ amd the odd one out.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Mon, 19 Mar 2018 20:51:02 GMT)
Full text and
rfc822 format available.
Message #104 received at 30078 <at> debbugs.gnu.org (full text, mbox):
>> lexbind-Elisp language is a strict superset of the
>> dynbind-Elisp language and for that reason I don't see any reason other
>> than backward compatibility to keep dynbind-Elisp.
>>
>> I'm not trying to fool people by "doing it one subtle step at a time",
>> I'm only trying to make this switch as painless as possible. I don't
>> yet have a plan for how we'll get rid of dynbind-Elisp and I'm sure
>> it'll take many years and several more steps, some of them less subtle
>> than others. Some of the steps I could imagine introducing in the not
>> too distant future:
>> - finish converting all Emacs's .el files to use lexical-binding:t.
>> - emit a warning when opening an Elisp file which doesn't specify
>> `lexical-binding:t' in its local vars.
>> - emit a warning when `eval` is called without a nil 2nd arg.
>
> Really? Get rid of dynamic binding in ELisp?
Not sure if by "dynamic binding" you mean "the variant of Elisp
corresponding to lexical-binding = nil" (which I call dynbind-Elisp) or
"some new Elisp variant where dynamic binding has been removed
altogether" (which doesn't currently exist AFAIK).
I have no intention to eliminate dynamic binding from Elisp at all.
What I'd like to see happen within the next, say, 20 years is to get rid
of the `lexical-binding` variable (i.e. treat everything as if this var
were always non-nil and as if `eval`s second arg was always non-nil), so
that dynamic binding only ever happens for those variables that have
been explicitly declared to be dynamic with `defvar` (as is the case in
what I call the lexbind-Elisp language).
> Why is that a good idea?
Because, having two languages is a bit inconvenient and brings extra
complexity: e.g. some code snippets only work right in one of the two
languages (usually nowadays it's in the lexbind variant, AFAICT), so you
need to label them appropriately.
> It would mean old code will not run in Emacs for no good reason.
That's true. Which is why it's a long-term goal only. Note that it's
usually easy to tweak that code to make it work again, tho it is
occasionally a bit more painful. And we usually introduce other
backward incompatibilities along the way, so it's rather rare for 20
year old Elisp code to still run correctly unmodified.
>> It's dynamic binding which is the odd one out
> Not for me, it isn't. Maybe that means _I_ amd the odd one out.
Beside Elisp, I know you're familiar with at least one other language
which only supports lexical scoping: C.
What other language(s) do you know/use? Which scoping do they support?
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Tue, 20 Mar 2018 07:00:01 GMT)
Full text and
rfc822 format available.
Message #107 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> From: Stefan Monnier <monnier <at> IRO.UMontreal.CA>
> Cc: michael_heerdegen <at> web.de, 30078 <at> debbugs.gnu.org
> Date: Mon, 19 Mar 2018 16:50:34 -0400
>
> > Really? Get rid of dynamic binding in ELisp?
>
> Not sure if by "dynamic binding" you mean "the variant of Elisp
> corresponding to lexical-binding = nil" (which I call dynbind-Elisp) or
> "some new Elisp variant where dynamic binding has been removed
> altogether" (which doesn't currently exist AFAIK).
>
> I have no intention to eliminate dynamic binding from Elisp at all.
> What I'd like to see happen within the next, say, 20 years is to get rid
> of the `lexical-binding` variable (i.e. treat everything as if this var
> were always non-nil and as if `eval`s second arg was always non-nil), so
> that dynamic binding only ever happens for those variables that have
> been explicitly declared to be dynamic with `defvar` (as is the case in
> what I call the lexbind-Elisp language).
>
> > Why is that a good idea?
>
> Because, having two languages is a bit inconvenient and brings extra
> complexity: e.g. some code snippets only work right in one of the two
> languages (usually nowadays it's in the lexbind variant, AFAICT), so you
> need to label them appropriately.
Are that inconvenience and complexity really so bad? They don't sound
like that.
> > It would mean old code will not run in Emacs for no good reason.
>
> That's true. Which is why it's a long-term goal only.
I'm asking why make it a goal at all.
> >> It's dynamic binding which is the odd one out
> > Not for me, it isn't. Maybe that means _I_ amd the odd one out.
>
> Beside Elisp, I know you're familiar with at least one other language
> which only supports lexical scoping: C.
Global variables in C are very similar to dynamic binding, so I had no
problem getting used to ELisp at the time.
> What other language(s) do you know/use? Which scoping do they support?
Every language I ever used (which is not a lot) supports global
variables, so again, no problems in that department.
Or maybe I again misunderstand what you mean by "dynbind".
Anyway, I don't think it's worth our while to discuss what is or isn't
a problem for me personally. The popular style of writing Emacs Lisp
nowadays is very different from what it was 20 or 25 years ago, when I
learned the language, which is an obstacle to someone like myself, who
is not very interested in programming languages and their facilities.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Tue, 20 Mar 2018 19:21:01 GMT)
Full text and
rfc822 format available.
Message #110 received at 30078 <at> debbugs.gnu.org (full text, mbox):
>> Because, having two languages is a bit inconvenient and brings extra
>> complexity: e.g. some code snippets only work right in one of the two
>> languages (usually nowadays it's in the lexbind variant, AFAICT), so you
>> need to label them appropriately.
> Are that inconvenience and complexity really so bad? They don't sound
> like that.
It's a source of bugs, slows down the interpreter, complicates the
compiler, complicates the doc, regularly confuses new users who copy
snippets of code and use them in the wrong language, ...
Also several macros need to know if the code they generate will be
interpreted in the lexbind-Elisp or the dynbind-Elisp language, so those
are also impacted.
The clear tendency is for new developments to drop support for
dynbind-Elisp whenever it gets in the way (e.g. some macros just signal
an error when used from dynbind-Elisp). So dynbind-Elisp is slowly
becoming second class citizen.
>> > It would mean old code will not run in Emacs for no good reason.
>> That's true. Which is why it's a long-term goal only.
> I'm asking why make it a goal at all.
I guess in the worst case we could keep it indefinitely. But I hope
that in the future no code ends up using dynbind-Elisp "by accident".
IOW dynbind-Elisp should only be used upon explicit request (e.g. by
setting lexical-binding to nil in the file-local vars or by passing
a special `:dynbind` second argument to `eval`).
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Mon, 02 Apr 2018 19:42:01 GMT)
Full text and
rfc822 format available.
Message #113 received at 30078 <at> debbugs.gnu.org (full text, mbox):
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
We need dynamic binding to run old programs which were written for it.
We must keep it running forever for that reason.
Aside from that, I don't see a case where we really need to use it.
The 'e' command in the debugger needs to give access to the bindings
of the code being debugged -- even if that code uses lexical binding.
There are various ways to implement that. How is it implemented now?
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Tue, 03 Apr 2018 00:13:02 GMT)
Full text and
rfc822 format available.
Message #116 received at 30078 <at> debbugs.gnu.org (full text, mbox):
> We need dynamic binding to run old programs which were written for it.
> We must keep it running forever for that reason.
In any case, I realized in the mean time that the issue is not so much
whether we'll keep this forever for backward compatibility but whether
we want to actively discourage its use.
> The 'e' command in the debugger needs to give access to the bindings
> of the code being debugged -- even if that code uses lexical binding.
> There are various ways to implement that. How is it implemented now?
It pays attention to the frame in which point is located when you hit
`e`, then "unwinds" the bindings on the stack upto that frame
temporarily while evaluating the code you typed.
That same mechanism happens to work both for the dynamically bound
variables and for the lexically bound ones (because the lexical
environment is kept internally by the interpreter in a dynamically bound
variable).
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#30078
; Package
emacs
.
(Tue, 03 Apr 2018 16:51:01 GMT)
Full text and
rfc822 format available.
Message #119 received at 30078 <at> debbugs.gnu.org (full text, mbox):
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> In any case, I realized in the mean time that the issue is not so much
> whether we'll keep this forever for backward compatibility but whether
> we want to actively discourage its use.
I think we don't need to worry about that in advance.
--
Dr Richard Stallman
President, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)
Skype: No way! See https://stallman.org/skype.html.
bug marked as fixed in version 27.1, send any further explanations to
30078 <at> debbugs.gnu.org and Stefan Monnier <monnier <at> IRO.UMontreal.CA>
Request was from
Glenn Morris <rgm <at> gnu.org>
to
control <at> debbugs.gnu.org
.
(Thu, 25 Apr 2019 23:57:02 GMT)
Full text and
rfc822 format available.
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Fri, 24 May 2019 11:24:06 GMT)
Full text and
rfc822 format available.
This bug report was last modified 5 years and 179 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.