From 2a8c00bfc073d8c42c5c325289a8eada2ae5b309 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Helary Date: Sat, 6 Jan 2024 15:55:58 +0000 Subject: [PATCH 1/4] * doc/emacs/back.texi: Fix a typo. --- doc/emacs/back.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/emacs/back.texi b/doc/emacs/back.texi index b8094c6cf36..ff6905d8b02 100644 --- a/doc/emacs/back.texi +++ b/doc/emacs/back.texi @@ -78,7 +78,7 @@ And much more! Emacs comes with an introductory online tutorial available in many languages, and this nineteenth edition of the manual picks up where that tutorial ends. It explains the full range of the power of Emacs, -now up to @strong[version 27.2,} and contains reference material +now up to @strong{version 27.2,} and contains reference material useful to expert users. It also includes appendices with specific material about X and GTK resources, and with details for users of macOS and Microsoft Windows. From 8729a2a10d9b8d88f6ba33b5ce62f74d89e7788a Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 6 Jan 2024 19:30:16 +0200 Subject: [PATCH 2/4] Fix 'rmail-summary-by-thread' * lisp/mail/rmailsum.el (rmail-summary-by-thread): Call 'rmail-new-summary' from the original buffer, not from 'rmail-buffer' to avoid failing the logic in 'rmail-new-summary' that decides whether to pop up a new window. Reported by Andrea Monaco . --- lisp/mail/rmailsum.el | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lisp/mail/rmailsum.el b/lisp/mail/rmailsum.el index 30fe75f7e5c..cccd702dae2 100644 --- a/lisp/mail/rmailsum.el +++ b/lisp/mail/rmailsum.el @@ -436,19 +436,19 @@ headers of the messages." (unless (and rmail-summary-message-parents-vector (= (length rmail-summary-message-parents-vector) (1+ rmail-total-messages))) - (rmail-summary-fill-message-parents-and-descs-vectors)) - (let ((enc-msgs (make-bool-vector (1+ rmail-total-messages) nil))) - (rmail-summary--walk-thread-message-recursively msgnum enc-msgs) - (rmail-new-summary (format "thread containing message %d" msgnum) - (list 'rmail-summary-by-thread msgnum) - (if (and rmail-summary-progressively-narrow - (rmail-summary--exists-1)) - (lambda (msg _msgnum) - (and (aref rmail-summary-currently-displayed-msgs msg) - (aref enc-msgs msg))) + (rmail-summary-fill-message-parents-and-descs-vectors))) + (let ((enc-msgs (make-bool-vector (1+ rmail-total-messages) nil))) + (rmail-summary--walk-thread-message-recursively msgnum enc-msgs) + (rmail-new-summary (format "thread containing message %d" msgnum) + (list 'rmail-summary-by-thread msgnum) + (if (and rmail-summary-progressively-narrow + (rmail-summary--exists-1)) (lambda (msg _msgnum) - (aref enc-msgs msg))) - msgnum)))) + (and (aref rmail-summary-currently-displayed-msgs msg) + (aref enc-msgs msg))) + (lambda (msg _msgnum) + (aref enc-msgs msg))) + msgnum))) ;;;###autoload (defun rmail-summary-by-labels (labels) From 1b123972636d717241a38bcd6daa3e3f424fb8b0 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 7 Jan 2024 17:15:18 +0200 Subject: [PATCH 3/4] ; Don't record multiple versions of use-package * lisp/use-package/use-package-ensure-system-package.el: Remove Version: header, to avoid confusing loaddefs-gene. (Bug#68304) --- lisp/use-package/use-package-ensure-system-package.el | 1 - 1 file changed, 1 deletion(-) diff --git a/lisp/use-package/use-package-ensure-system-package.el b/lisp/use-package/use-package-ensure-system-package.el index 12bf16998a1..3e369d99624 100644 --- a/lisp/use-package/use-package-ensure-system-package.el +++ b/lisp/use-package/use-package-ensure-system-package.el @@ -5,7 +5,6 @@ ;; Author: Justin Talbott ;; Keywords: convenience, tools, extensions ;; URL: https://github.com/waymondo/use-package-ensure-system-package -;; Version: 0.2 ;; Package-Requires: ((use-package "2.1") (system-packages "1.0.4")) ;; Filename: use-package-ensure-system-package.el ;; Package: use-package From d58d0fa52ff22e147b8328759d5f0f762e15bbb5 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Wed, 25 Oct 2023 20:43:57 -0700 Subject: [PATCH 4/4] Introduce 'let' using lexical binding in the Lisp Introduction * doc/lispintro/emacs-lisp-intro.texi (Prevent confusion): Rework the explanation to discuss how things work under lexical binding. (How let Binds Variables): Describe the differences between lexical and dynamic binding (including how to configure it). (defvar): Mention that 'defvar' declares variables as always dynamically-bound (bug#66756). --- doc/lispintro/emacs-lisp-intro.texi | 171 ++++++++++++++++++++++++---- 1 file changed, 149 insertions(+), 22 deletions(-) diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 1e10f62104a..b3fe8ce4589 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -3556,6 +3556,7 @@ and the two are not intended to refer to the same value. The * Parts of let Expression:: * Sample let Expression:: * Uninitialized let Variables:: +* How let Binds Variables:: @end menu @ifnottex @@ -3569,24 +3570,26 @@ and the two are not intended to refer to the same value. The @cindex @samp{variable, local}, defined The @code{let} special form prevents confusion. @code{let} creates a name for a @dfn{local variable} that overshadows any use of the same -name outside the @code{let} expression. This is like understanding -that whenever your host refers to ``the house'', he means his house, not -yours. (Symbols used in argument lists work the same way. +name outside the @code{let} expression (in computer science jargon, we +call this @dfn{binding} the variable). This is like understanding +that in your host's home, whenever he refers to ``the house'', he +means his house, not yours. (The symbols used to name function +arguments are bound as local variables in exactly the same way. @xref{defun, , The @code{defun} Macro}.) -Local variables created by a @code{let} expression retain their value -@emph{only} within the @code{let} expression itself (and within -expressions called within the @code{let} expression); the local -variables have no effect outside the @code{let} expression. - -Another way to think about @code{let} is that it is like a @code{setq} -that is temporary and local. The values set by @code{let} are -automatically undone when the @code{let} is finished. The setting -only affects expressions that are inside the bounds of the @code{let} -expression. In computer science jargon, we would say the binding of -a symbol is visible only in functions called in the @code{let} form; -in Emacs Lisp, the default scoping is dynamic, not lexical. (The -non-default lexical binding is not discussed in this manual.) +Another way to think about @code{let} is that it defines a special +region in your code: within the body of the @code{let} expression, the +variables you've named have their own local meaning. Outside of the +@code{let} body, they have other meanings (or they may not be defined +at all). This means that inside the @code{let} body, calling +@code{setq} for a variable named by the @code{let} expression will set +the value of the @emph{local} variable of that name. However, outside +of the @code{let} body (such as when calling a function that was +defined elsewhere), calling @code{setq} for a variable named by the +@code{let} expression will @emph{not} affect that local +variable.@footnote{This describes the behavior of @code{let} when +using a style called ``lexical binding'' (@pxref{How let Binds +Variables}).} @code{let} can create more than one variable at once. Also, @code{let} gives each variable it creates an initial value, either a @@ -3746,6 +3749,128 @@ number is printed in the message using a @samp{%d} rather than a @samp{%s}.) The four variables as a group are put into a list to delimit them from the body of the @code{let}. +@node How let Binds Variables +@subsection How @code{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). +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{Selecting Lisp Dialect, , , +elisp, The Emacs Lisp Reference Manual}. + +@menu +* Lexical & Dynamic Binding Differences:: +* Lexical vs. Dynamic Binding Example:: +@end menu + +@node Lexical & Dynamic Binding Differences +@unnumberedsubsubsec Differences Between Lexical and Dynamic Binding + +@cindex Lexical binding +@cindex Binding, lexical +As we discussed before (@pxref{Prevent confusion}), when you create +local variables with @code{let} under lexical binding, those variables +are valid only within the body of the @code{let} expression. In other +parts of your code, they have other meanings, so if you call a +function defined elsewhere within the @code{let} body, that function +would be unable to ``see'' the local variables you've created. (On +the other hand, if you call a function that was defined within a +@code{let} body, that function @emph{would} be able to see---and +modify---the local variables from that @code{let} expression.) + +@cindex Dynamic binding +@cindex Binding, dynamic +Under dynamic binding, the rules are different: instead, when you use +@code{let}, the local variables you've created are valid during +execution of the @code{let} expression. This means that, if your +@code{let} expression calls a function, that function can see these +local variables, regardless of where the function is defined +(including in another file entirely). + +Another way to think about @code{let} when using dynamic binding is +that every variable name has a global ``stack'' of bindings, and +whenever you use that variable's name, it refers to the binding on the +top of the stack. (You can imagine this like a stack of papers on +your desk with the values written on them.) When you bind a variable +dynamically with @code{let}, it puts the new binding you've specified +on the top of the stack, and then executes the @code{let} body. Once +the @code{let} body finishes, it takes that binding off of the stack, +revealing the one it had (if any) before the @code{let} expression. + +@node Lexical vs. Dynamic Binding Example +@unnumberedsubsubsec Example of Lexical vs. Dynamic Binding +In some cases, both lexical and dynamic binding behave identically. +However, in other cases, they can change the meaning of your program. +For example, see what happens in this code under lexical binding: + +@example +;;; -*- lexical-binding: t -*- + +(setq x 0) + +(defun getx () + x) + +(setq x 1) + +(let ((x 2)) + (getx)) + @result{} 1 +@end example + +@noindent +Here, the result of @code{(getx)} is @code{1}. Under lexical binding, +@code{getx} doesn't see the value from our @code{let} expression. +That's because the body of @code{getx} is outside of the body of our +@code{let} expression. Since @code{getx} is defined at the top, +global level of our code (i.e.@: not inside the body of any @code{let} +expression), it looks for and finds @code{x} at the global level as +well. When executing @code{getx}, the current global value of +@code{x} is @code{1}, so that's what @code{getx} returns. + +If we use dynamic binding instead, the behavior is different: + +@example +;;; -*- lexical-binding: nil -*- + +(setq x 0) + +(defun getx () + x) + +(setq x 1) + +(let ((x 2)) + (getx)) + @result{} 2 +@end example + +@noindent +Now, the result of @code{(getx)} is @code{2}! That's because under +dynamic binding, when executing @code{getx}, the current binding for +@code{x} at the top of our stack is the one from our @code{let} +binding. This time, @code{getx} doesn't see the global value for +@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, , +Initializing a Variable with @code{defvar}}.) + @node if @section The @code{if} Special Form @findex if @@ -9101,12 +9226,14 @@ In Emacs Lisp, a variable such as the @code{kill-ring} is created and given an initial value by using the @code{defvar} special form. The name comes from ``define variable''. -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 two ways: first, -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 existing value. Second, @code{defvar} has a -documentation string. +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} +(@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 +existing value. Third, @code{defvar} has a documentation string. (There is a related macro, @code{defcustom}, designed for variables that people customize. It has more features than @code{defvar}.