From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#74145: 31.0.50; Default lexical-binding to t Date: Thu, 31 Oct 2024 16:57:57 -0400 Message-ID: Reply-To: Stefan Monnier Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="34271"; mail-complaints-to="usenet@ciao.gmane.io" Cc: monnier@iro.umontreal.ca To: 74145@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Thu Oct 31 21:59:23 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1t6cGI-0008ex-3U for geb-bug-gnu-emacs@m.gmane-mx.org; Thu, 31 Oct 2024 21:59:22 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t6cG0-0002gm-3x; Thu, 31 Oct 2024 16:59:04 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t6cFz-0002gc-5I for bug-gnu-emacs@gnu.org; Thu, 31 Oct 2024 16:59:03 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t6cFy-0004Ss-T5 for bug-gnu-emacs@gnu.org; Thu, 31 Oct 2024 16:59:02 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:From:To:Subject; bh=y4XxuX/q3jFSWdZv8AlzlA2EM4poCXDarlwjHWlpbmg=; b=kLzzrXDWXijewXzxw3S8pdg6TvkTNWouX0ajxzv50nFTGlMhxm99LSu45pBzsVXNDIKetNA9O48ckutpWUkBm/qTTBW4ctsEo98Z7uDm03g/2O+YB/FXD/I+NtT4GJMP5toTNUykqe3ub31UvfEGGuUirJlohKjk3fDHg4IC9/Wj0/lNRil1g106iFZ4uMA3/J9kibnrinYCd4sh5dpiSb7o7GQXnxAE6LH9+u31zvHQNtS6Rv7xIhV7PlnZYDnav2HzOeDCzQ4+h0JI1S1A8UkK9p1U02WgwHDGp6VlP6sIOUzfIQgwceROy24hvJeTeFxSK7dAhkMPHNKrf6cOTQ==; Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1t6cFy-00005v-Gz; Thu, 31 Oct 2024 16:59:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: monnier@iro.umontreal.ca, bug-gnu-emacs@gnu.org Resent-Date: Thu, 31 Oct 2024 20:59:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 74145 X-GNU-PR-Package: emacs X-Debbugs-Original-To: bug-gnu-emacs@gnu.org X-Debbugs-Original-Xcc: monnier@iro.umontreal.ca Original-Received: via spool by submit@debbugs.gnu.org id=B.1730408314319 (code B ref -1); Thu, 31 Oct 2024 20:59:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 31 Oct 2024 20:58:34 +0000 Original-Received: from localhost ([127.0.0.1]:44279 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1t6cFU-000055-RT for submit@debbugs.gnu.org; Thu, 31 Oct 2024 16:58:33 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:43434) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1t6cFR-00004y-A2 for submit@debbugs.gnu.org; Thu, 31 Oct 2024 16:58:31 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t6cFR-0002fF-55 for bug-gnu-emacs@gnu.org; Thu, 31 Oct 2024 16:58:29 -0400 Original-Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t6cFI-0004RY-R0 for bug-gnu-emacs@gnu.org; Thu, 31 Oct 2024 16:58:28 -0400 Original-Received: from pmg3.iro.umontreal.ca (localhost [127.0.0.1]) by pmg3.iro.umontreal.ca (Proxmox) with ESMTP id B55DF442D4B for ; Thu, 31 Oct 2024 16:58:17 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1730408290; bh=9wVbgfa2YZt+m+ub49847lhDxBpFkGa8bv6V2DxD1cU=; h=From:To:Subject:Date:From; b=nzAj5+B3PhvGNm+CQHHqpeW9Xpx8kkccgs/ciYqxY+VhnnPKKrgdQUOyQQatIpoRM uwS0b6W2XDr+zA+sO4vGtgBcW+NZ1p3BlzsFYKo7JnXhnNYJ0Con2TDBFGymYiMnZK zyoYaS34M7ajwJxIEOYiyE3bTT3f5OrunqgFBrD+qj/gTQ7cdYq8tkKu23hG2/VAuX IPn/jF81aZkk65TsmkZM/CixoAWVWN1VwLimVuUTv07Afe8JivXtqjjMibpyV0BGxY bkNbDe3Ff4UdK1qFdfyozZQH1ynjixHw3kBTD0R2dTJW9rtnx/ObBHR0GE3r4c8Ggl tYBqsxxs+2Uiw== Original-Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg3.iro.umontreal.ca (Proxmox) with ESMTP id 7447744295B for ; Thu, 31 Oct 2024 16:58:10 -0400 (EDT) Original-Received: from pastel (unknown [104.195.225.43]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 518DA1201CF for ; Thu, 31 Oct 2024 16:58:10 -0400 (EDT) Received-SPF: pass client-ip=132.204.25.50; envelope-from=monnier@iro.umontreal.ca; helo=mailscanner.iro.umontreal.ca X-Spam_score_int: -42 X-Spam_score: -4.3 X-Spam_bar: ---- X-Spam_report: (-4.3 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:294637 Archived-At: --=-=-= Content-Type: text/plain Package: Emacs Version: 31.0.50 I believe the time has come to change the default dialect. I attached a suggested patch to do that. Stefan --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-Change-the-default-value-of-lexical-binding.patch >From 973939b9dd79735f051c99f1a20d74aabad931ff Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Thu, 31 Oct 2024 16:00:10 -0400 Subject: [PATCH] Change the default value of `lexical-binding` * src/lread.c (syms_of_lread): Set `Vlexical_binding` to Qt. (Fload, Feval_buffer): Don't assume the default value of `lexical-binding` is nil. * lisp/loadup.el: Don't assume the default value of `lexical-binding` is nil. * doc/misc/cl.texi (Porting Common Lisp): * doc/lispref/variables.texi (Variable Scoping) (Selecting Lisp Dialect): Adjust to new default of `lexical-binding`. * doc/lispref/edebug.texi (Edebug Eval): Remove out of date paragraph. * doc/lispintro/emacs-lisp-intro.texi (How let Binds Variables) (Lexical vs. Dynamic Binding Example, defvar): Only consider the lexical dialect of ELisp. --- doc/lispintro/emacs-lisp-intro.texi | 26 ++++++++---------------- doc/lispref/edebug.texi | 7 ------- doc/lispref/variables.texi | 31 +++++++++++++++-------------- doc/misc/cl.texi | 9 +++++---- etc/NEWS | 6 ++++++ lisp/loadup.el | 4 ++-- src/lread.c | 14 +++++++++---- 7 files changed, 47 insertions(+), 50 deletions(-) diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 49916235fbf..6cc7a5b3cf2 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -3754,21 +3754,12 @@ How let Binds Variables Emacs Lisp supports two different ways of binding variable names to their values. These ways affect the parts of your program where a -particular binding is valid. For historical reasons, Emacs Lisp uses -a form of variable binding called @dfn{dynamic binding} by default. -However, in this manual we discuss the preferred form of binding, -called @dfn{lexical binding}, unless otherwise noted (in the future, -the Emacs maintainers plan to change the default to lexical binding). +particular binding is valid. +In this manual we discuss the preferred form of binding, +called @dfn{lexical binding}, unless otherwise noted. If you have programmed in other languages before, you're likely already familiar with how lexical binding behaves. -In order to use lexical binding in a program, you should add this to -the first line of your Emacs Lisp file: - -@example -;;; -*- lexical-binding: t -*- -@end example - For more information about this, @pxref{Variable Scoping, , , elisp, The Emacs Lisp Reference Manual}. @@ -3818,8 +3809,6 @@ Lexical vs. Dynamic Binding Example For example, see what happens in this code under lexical binding: @example -;;; -*- lexical-binding: t -*- - (setq x 0) (defun getx () @@ -3845,7 +3834,7 @@ Lexical vs. Dynamic Binding Example If we use dynamic binding instead, the behavior is different: @example -;;; -*- lexical-binding: nil -*- +(defvar x) ;; Use dynamic binding for 'x'. (setq x 0) @@ -3867,8 +3856,9 @@ Lexical vs. Dynamic Binding Example @code{x}, since its binding is below the one from our @code{let} expression in the stack of bindings. -(Some variables are also ``special'', and they are always dynamically -bound even when @code{lexical-binding} is @code{t}. @xref{defvar, , +(The @code{defvar} declaration above is said to make the variable +``special'', which causes it to obey the dynamic binding rules instead of +the default lexical binding rules. @xref{defvar, , Initializing a Variable with @code{defvar}}.) @node if @@ -9229,7 +9219,7 @@ defvar The @code{defvar} special form is similar to @code{setq} in that it sets the value of a variable. It is unlike @code{setq} in three ways: first, it marks the variable as ``special'' so that it is always -dynamically bound, even when @code{lexical-binding} is @code{t} +dynamically bound (@pxref{How let Binds Variables}). Second, it only sets the value of the variable if the variable does not already have a value. If the variable already has a value, @code{defvar} does not override the diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi index 03fae67e528..fe617550b09 100644 --- a/doc/lispref/edebug.texi +++ b/doc/lispref/edebug.texi @@ -722,13 +722,6 @@ Edebug Eval pretty-printed in a separate buffer. @end table -@cindex lexical binding (Edebug) - Edebug supports evaluation of expressions containing references to -lexically bound symbols created by the following constructs in -@file{cl.el}: @code{lexical-let}, @code{macrolet}, and -@code{symbol-macrolet}. -@c FIXME? What about lexical-binding = t? - @node Eval List @subsection Evaluation List Buffer diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index af11e498d86..fa5f792b40f 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -285,7 +285,7 @@ Local Variables @defspec letrec (bindings@dots{}) forms@dots{} This special form is like @code{let*}, but all the variables are bound before any of the local values are computed. The values are then -assigned to the locally bound variables. This is only useful when +assigned to the locally bound variables. This is useful only when lexical binding is in effect, and you want to create closures that refer to bindings that would otherwise not yet be in effect when using @code{let*}. @@ -351,7 +351,7 @@ Local Variables done so that the value returned by the call is the value of @var{body} itself, as is the case in the recursive call to @code{sum} above. -@code{named-let} can only be used when lexical-binding is enabled. +@code{named-let} can be used only when lexical-binding is enabled. @xref{Lexical Binding}. @end defspec @@ -392,7 +392,7 @@ Void Variables to evaluate the variable signals a @code{void-variable} error, instead of returning a value. - Under the optional lexical scoping rule, the value cell only holds + Under the optional lexical scoping rule, the value cell holds only the variable's global value---the value outside of any lexical binding construct. When a variable is lexically bound, the local value is determined by the lexical environment; hence, variables can have local @@ -514,7 +514,7 @@ Defining Variables Note that specifying a value, even @code{nil}, marks the variable as special permanently. Whereas if @var{value} is omitted then the -variable is only marked special locally (i.e.@: within the current +variable is marked special only locally (i.e.@: within the current lexical scope, or file if at the top-level). This can be useful for suppressing byte compilation warnings, see @ref{Compiler Errors}. @@ -706,8 +706,8 @@ Accessing Variables The usual way to reference a variable is to write the symbol which names it. @xref{Symbol Forms}. - Occasionally, you may want to reference a variable which is only -determined at run time. In that case, you cannot specify the variable + Occasionally, you may want to reference a variable which is determined +only at run time. In that case, you cannot specify the variable name in the text of the program. You can use the @code{symbol-value} function to extract the value. @@ -1003,14 +1003,15 @@ Variable Scoping while the binding construct (such as the body of a @code{let} form) is being executed. - The old dynamic-only Emacs Lisp dialect is still the default in code + The new lexically scoped Emacs Lisp dialect is now the default in code loaded or evaluated from Lisp files that lack a dialect declaration. -Eventually the modern dialect will be made the default. -All Lisp files should declare the dialect used to ensure that they -keep working correctly in the future. +Lisp files which still need the old dynamically scoped dialect need to declare +it explicitly to ensure that they keep working correctly, and should +eventually be converted to use the new dialect to +ensure that they keep working correctly in the future. The following subsections describe lexical binding and dynamic -binding in greater detail, and how to enable lexical binding in Emacs +binding in greater detail, and how to disable lexical binding in Emacs Lisp programs. @menu @@ -1319,8 +1320,8 @@ Selecting Lisp Dialect @noindent for the old dynamic-only dialect. When no declaration is present the -old dialect is used, but this may change in a future release. -The compiler will warn if no declaration is present. +new dialect is used. Support for the old dialect may be removed in +a future release. When evaluating Emacs Lisp code directly using an @code{eval} call, lexical binding is enabled if the @var{lexical} argument to @@ -1980,8 +1981,8 @@ File Local Variables @defvar permanently-enabled-local-variables Some local variable settings will, by default, be heeded even if -@code{enable-local-variables} is @code{nil}. By default, this is only -the case for the @code{lexical-binding} local variable setting, but +@code{enable-local-variables} is @code{nil}. By default, this is the +case only for the @code{lexical-binding} local variable setting, but this can be controlled by using this variable, which is a list of symbols. @end defvar diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi index 113029700ec..395725944f0 100644 --- a/doc/misc/cl.texi +++ b/doc/misc/cl.texi @@ -4758,12 +4758,13 @@ Porting Common Lisp @item Lexical scoping. In Common Lisp, function arguments and @code{let} bindings apply only to references physically within their bodies (or -within macro expansions in their bodies). Traditionally, Emacs Lisp -uses @dfn{dynamic scoping} wherein a binding to a variable is visible +within macro expansions in their bodies). The is also the case in +modern Emacs Lisp, but historically, Emacs Lisp +used @dfn{dynamic scoping} wherein a binding to a variable is visible even inside functions called from the body. @xref{Dynamic Binding,,,elisp,GNU Emacs Lisp Reference Manual}. -Lexical binding is available since Emacs 24.1, so be sure to set -@code{lexical-binding} to @code{t} if you need to emulate this aspect +Lexical binding is available since Emacs 24.1, but be sure not to set +@code{lexical-binding} to @code{nil} if you need to emulate this aspect of Common Lisp. @xref{Lexical Binding,,,elisp,GNU Emacs Lisp Reference Manual}. Here is an example of a Common Lisp code fragment that would fail in diff --git a/etc/NEWS b/etc/NEWS index d1c7303f976..5a480c5f68a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -636,6 +636,12 @@ the directory into which the repository was cloned. * Incompatible Lisp Changes in Emacs 31.1 ++++ +** 'lexical-binding' now defaults to t. +The default ELisp dialect is now the lexically scoped dialect. +Any code which has not yet been adapted should either be +adapted or set 'lexical-binding' to nil explicitly. + ** Nested backquotes are not supported any more in Pcase patterns. ** The 'rx' category name 'chinese-two-byte' must now be spelled correctly. diff --git a/lisp/loadup.el b/lisp/loadup.el index bd74a9d6aff..e676c338c14 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -654,9 +654,9 @@ comp-subr-arities-h (unwind-protect (let ((tmp-dump-mode dump-mode) (dump-mode nil) - ;; Set `lexical-binding' to nil by default + ;; Set `lexical-binding' to its default value ;; in the dumped Emacs. - (lexical-binding nil)) + (lexical-binding (default-toplevel-value 'lexical-binding))) (if (member tmp-dump-mode '("pdump" "pbootstrap")) (dump-emacs-portable (expand-file-name output invocation-directory)) (dump-emacs output (if (eq system-type 'ms-dos) diff --git a/src/lread.c b/src/lread.c index ea0398196e3..9f56880e551 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1522,7 +1522,7 @@ DEFUN ("load", Fload, Sload, 1, 5, 0, otherwise using a file-variable in the first line. This is bound here so that it takes effect whether or not we use Vload_source_file_function. */ - specbind (Qlexical_binding, Qnil); + specbind (Qlexical_binding, Fdefault_toplevel_value (Qlexical_binding)); Lisp_Object found_eff = is_native_elisp @@ -1720,8 +1720,11 @@ DEFUN ("load", Fload, Sload, 1, 5, 0, } else { - if (lisp_file_lexical_cookie (Qget_file_char) == Cookie_Lex) + lexical_cookie_t lexc = lisp_file_lexical_cookie (Qget_file_char); + if (lexc == Cookie_Lex) Fset (Qlexical_binding, Qt); + else if (lexc == Cookie_Dyn) + Fset (Qlexical_binding, Qnil); if (! version || version >= 22) readevalloop (Qget_file_char, &input, hist_file_name, @@ -2606,8 +2609,11 @@ DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0, 5, "", specbind (Qstandard_output, tem); record_unwind_protect_excursion (); BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); + lexical_cookie_t lexc = lisp_file_lexical_cookie (buf); specbind (Qlexical_binding, - lisp_file_lexical_cookie (buf) == Cookie_Lex ? Qt : Qnil); + lexc == Cookie_Lex ? Qt + : lexc == Cookie_Dyn ? Qnil + : Fdefault_toplevel_value (Qlexical_binding)); BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); readevalloop (buf, 0, filename, !NILP (printflag), unibyte, Qnil, Qnil, Qnil); @@ -6056,7 +6062,7 @@ syms_of_lread (void) This variable is automatically set from the file variables of an interpreted Lisp file read using `load'. Unlike other file local variables, this must be set in the first line of a file. */); - Vlexical_binding = Qnil; + Vlexical_binding = Qt; Fmake_variable_buffer_local (Qlexical_binding); DEFVAR_LISP ("eval-buffer-list", Veval_buffer_list, -- 2.39.5 --=-=-=--