Subject: bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual

From: Jim Porter <[email-masked]>
Date: Thu, 23 Nov 2023 13:04:01 -0800

On 11/22/2023 6:57 PM, Richard Stallman wrote:
> it could be good to add the following:
[snip]
> to show that `getx' accesses the current value of the global binding,
> not the value that the global binding had when getx was defined.

How about this? Instead of adding further examples, I made the existing 
ones just a bit more complex (I added another 'setq' after defining the 
function 'getx' to both examples). Then I explained specifically that in 
the lexical binding example, "... 'getx' sees the current global value 
of 'x'."

Hopefully this strikes the right balance between being explicit and 
detailed about what's happening without adding too many twists and turns 
to the section. I wanted to stick with just two blocks of code in this 
section so that a reader who was skimming (or just reading quickly) 
could easily pick them out to compare and contrast with each other. 
Additional code blocks made this harder to do when I tried it.

From fdfae219bec8255e173e8ef448f3b49de6fcc753 Mon Sep 17 00:00:00 2001
From: Jim Porter <[email-masked]>
Date: Wed, 25 Oct 2023 20:43:57 -0700
Subject: [PATCH] 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 | 142 +++++++++++++++++++++++-----
 1 file changed, 119 insertions(+), 23 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index c5b33ac5eaa..92287a4110c 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -3591,6 +3591,7 @@ let
 * Parts of let Expression::
 * Sample let Expression::
 * Uninitialized let Variables::
+* How let Binds Variables::
 @end menu
 
 @ifnottex
@@ -3601,25 +3602,22 @@ Prevent confusion
 @cindex @samp{local variable} defined
 @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 for a @dfn{local variable} that overrides any use of the same
+name outside the @code{let} expression (in computer science jargon, we
+call this ``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.  (Symbols used in argument lists work 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 place in
+your code where the variables you named have their own local meaning.
+Outside of the @code{let} body, they have another meaning (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.  This
+also means that outside of the @code{let} body, calling @code{setq}
+for a variable named by the @code{let} expression will @emph{not}
+affect that local variable.
 
 @code{let} can create more than one variable at once.  Also,
 @code{let} gives each variable it creates an initial value, either a
@@ -3779,6 +3777,102 @@ Uninitialized let Variables
 @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
+@cindex Lexical binding
+@cindex Binding, lexical
+@cindex Dynamic binding
+@cindex Binding, dynamic
+
+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 (in computer science jargon, we call these
+parts a ``scope'').  For historical reasons, Emacs Lisp uses a form of
+variable binding called ``dynamic binding'' by default.  However, in
+this manual we discuss the preferred form of binding, called ``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}.
+
+As we discussed before, under lexical binding, @code{let} defines a
+@emph{place} in your code where the variables have their own local
+meaning.  Under dynamic binding, the rules are different: instead, you
+are defining a @emph{time} in your code when the variables have their
+own local meaning.
+
+Another way to think about @code{let} when using dynamic binding 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 some cases, both lexical and dynamic binding behave identically.
+However, in other cases, they can change the meaning of your program.
+For example, under lexical binding, if you call a function inside of a
+@code{let} body, that function's body would be unable to ``see'' (or
+modify) the value of a local variable from the @code{let} expression:
+
+@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 it happens in a different @emph{place} than the
+@code{let} body.  Instead, @code{getx} sees the current global value
+of @code{x}.
+
+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
+
+@noident
+Now, the result of @code{(getx)} is @code{2}!  That's because under
+dynamic binding, when @code{getx} looks for the value of @code{x}, it
+sees the value we set in our @code{let} expression.  In other words,
+the call to @code{getx} happens during the @emph{time} when our
+@code{let} expression is active.
+
+(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
@@ -9130,12 +9224,14 @@ defvar
 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 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, 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}).  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}.
-- 
2.25.1