all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
@ 2023-10-26  5:54 Jim Porter
  2023-10-26 18:30 ` Jim Porter
                   ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Jim Porter @ 2023-10-26  5:54 UTC (permalink / raw)
  To: 66756

[-- Attachment #1: Type: text/plain, Size: 630 bytes --]

(Spun out from bug#66706. My previous message below.)

On 10/25/2023 8:48 PM, Jim Porter wrote:
 > On 10/25/2023 6:19 PM, Jim Porter wrote:
 >> I'll start with a patch here then. I think this is also a prime spot
 >> to add an example or two that would actually show lexical binding in
 >> action (i.e. a sample where the code would do something different
 >> under dynamic binding).
 >
 > Here's a first attempt. I'm not sure I'm entirely happy with it (the
 > digression into setting 'lexical-binding' to 't' is a bit disruptive),
 > but hopefully it's an improvement. Of course, we can keep adjusting this
 > further as needed.

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 4916 bytes --]

From 6bc9bbbb98105f700bb8d5b04e8de5e261efa777 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
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): Rename to...
(Why Use let?): ... this, and rework the explanation to discuss
lexical binding (including how to enable it).
---
 doc/lispintro/emacs-lisp-intro.texi | 81 +++++++++++++++++++++--------
 1 file changed, 58 insertions(+), 23 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index fce7583fe91..ebbcc08b9ff 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -3587,39 +3587,74 @@ let
 @code{let} special form prevents this kind of confusion.
 
 @menu
-* Prevent confusion::
+* Why Use let?::
 * Parts of let Expression::
 * Sample let Expression::
 * Uninitialized let Variables::
 @end menu
 
 @ifnottex
-@node Prevent confusion
-@unnumberedsubsec @code{let} Prevents Confusion
+@node Why Use let?
+@unnumberedsubsec Why Use @code{let}?
 @end ifnottex
 
 @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.
-@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.)
+The @code{let} special form provides a way to confine your variables
+to a particular section of your code (in computer science jargon, a
+``scope'').  @code{let} creates a name for a @dfn{local variable} that
+overshadows any use of the same name outside the @code{let} expression
+(we call this ``binding'' the variable).  This prevents any accidental
+usage of these variables outside of 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.  @xref{defun, , The @code{defun} Macro}.)
+
+@cindex lexical binding
+@cindex binding, lexical
+@cindex dynamic binding
+@cindex binding, dynamic
+Before we begin discussing @code{let} in detail, we must first mention
+an important note.  For historical reasons, Emacs Lisp uses a form of
+variable binding called ``dynamic binding''.  However, this manual
+will discuss the preferred form of binding, called ``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, you should add something like 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}.
+
+With that out of the way, we can return to discussing @code{let}.
+Local variables created by a @code{let} expression hold their value
+@emph{only} within the body of the @code{let} expression itself; the
+local variables have no effect outside of the @code{let} expression.
+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.
+
+For example, 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
+(setq x 1)
+
+(defun getx ()
+  x)
+
+(let ((x 2))
+  (get-x))
+     @result{} 1
+@end example
 
 @code{let} can create more than one variable at once.  Also,
 @code{let} gives each variable it creates an initial value, either a
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-10-26  5:54 bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual Jim Porter
@ 2023-10-26 18:30 ` Jim Porter
  2023-10-29 16:38   ` Richard Stallman
  2023-11-04  8:27   ` Eli Zaretskii
  2023-11-06  2:29 ` Richard Stallman
  2023-11-06  2:29 ` Richard Stallman
  2 siblings, 2 replies; 33+ messages in thread
From: Jim Porter @ 2023-10-26 18:30 UTC (permalink / raw)
  To: 66756, eliz

[-- Attachment #1: Type: text/plain, Size: 2116 bytes --]

On 10/26/2023 12:09 AM, Eli Zaretskii wrote:
 > Thanks.
 >
 > The challenge in updating the Lisp Introduction manual is to try to
 > keep its informal and reader-friendly style as much as possible.  It
 > is not just another ELisp Reference manual!  So please try to keep
 > that in mind when you write the text, and in particular try not to
 > modify the existing text that is still accurate -- it was written by a
 > master, and each word there counts, even if it looks at first sight as
 > not important.

Ok, here's a second attempt. I've tried to avoid changing anything that 
I don't think is truly necessary. I did alter a bit of the original 
wording to emphasize that under lexical binding, 'let' isn't about time, 
but about place. For example, that's why I changed this:

> This is like understanding that whenever your host refers to ``the house'', he means his house, not yours.

to this:

> This is like understanding that in your host's home, whenever he refers to ``the house'', he means his house, not yours.

My previous concern about the "lexical binding" digression still applies 
though. However, I'm not sure how to get around that at present; if we 
want to talk about lexical binding in the manual, we need to get users 
to enable it, so I think it's unavoidable that we at least mention it. I 
tried to introduce the jargon as gently as I could (by first introducing 
the term "binding" on its own before mentioning "lexical/dynamic 
binding"), but it's still a bit intimidating. On the positive side, when 
lexical binding is the default, we could remove that entire digression.

There's also an argument that the example I added is in the wrong spot, 
since we haven't actually introduced the 'let' syntax yet. However, I 
personally find the example to be pretty useful since it shows off one 
of the key differences between lexical and dynamic binding, and helps 
show one of the boundaries of the 'let' form's scope. I myself tend to 
learn best by seeing examples of that sort. Fixing the order so we 
introduce the syntax first would require more extensive changes to this 
section...

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 4191 bytes --]

From 12847e0d59b2de3791efa090addc0169e713e6d1 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
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
(including how to enable it).
---
 doc/lispintro/emacs-lisp-intro.texi | 67 ++++++++++++++++++++++-------
 1 file changed, 51 insertions(+), 16 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index fce7583fe91..e805833f979 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -3602,24 +3602,59 @@ Prevent confusion
 @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 ``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.)
+@cindex lexical binding
+@cindex binding, lexical
+@cindex dynamic binding
+@cindex binding, dynamic
+Before we begin discussing @code{let} in detail, we must first mention
+an important note.  For historical reasons, Emacs Lisp uses a form of
+variable binding called ``dynamic binding''.  However, this manual
+will discuss the preferred form of binding, called ``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, you should add something like 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}.
+
+With that out of the way, we can get back to discussing @code{let}.
+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.
+
+For example, 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
+(setq x 1)
+
+(defun getx ()
+  x)
+
+(let ((x 2))
+  (get-x))
+     @result{} 1
+@end example
 
 @code{let} can create more than one variable at once.  Also,
 @code{let} gives each variable it creates an initial value, either a
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-10-26 18:30 ` Jim Porter
@ 2023-10-29 16:38   ` Richard Stallman
  2023-10-29 17:18     ` Drew Adams
  2023-11-18  2:09     ` Jim Porter
  2023-11-04  8:27   ` Eli Zaretskii
  1 sibling, 2 replies; 33+ messages in thread
From: Richard Stallman @ 2023-10-29 16:38 UTC (permalink / raw)
  To: Jim Porter; +Cc: eliz, 66756

[[[ 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. ]]]

  > > This is like understanding that in your host's home, whenever he refers to ``the house'', he means his house, not yours.

That seems good enough to me.

  > My previous concern about the "lexical binding" digression still applies 
  > though. However, I'm not sure how to get around that at present; if we 
  > want to talk about lexical binding in the manual, we need to get users 
  > to enable it, so I think it's unavoidable that we at least mention it. 

I think that the lexical/dynamic scope distinction is sufficiently
important that this manual should explain it, whether or not hiding it
is simply impossible.

However, tehre are lots of simple Lisp functions for which lexical
vs dynamic maks no diffeence.  For example,

(defun square (x)
  (* x x))

So perhaps it is possible for the first few sections to use examples
which work the same in lexical mode and dynamic mode, THEN show an
example for which it does make a difference as a way to explain the
two modes.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-10-29 16:38   ` Richard Stallman
@ 2023-10-29 17:18     ` Drew Adams
  2023-11-18  2:09     ` Jim Porter
  1 sibling, 0 replies; 33+ messages in thread
From: Drew Adams @ 2023-10-29 17:18 UTC (permalink / raw)
  To: rms@gnu.org, Jim Porter; +Cc: eliz@gnu.org, 66756@debbugs.gnu.org

> I think that the lexical/dynamic scope distinction is sufficiently
> important that this manual should explain it, whether or not hiding it
> is simply impossible.
> 
> However, tehre are lots of simple Lisp functions for which lexical
> vs dynamic maks no diffeence.  For example, (defun square (x) (* x x))
> 
> So perhaps it is possible for the first few sections to use examples
> which work the same in lexical mode and dynamic mode, THEN show an
> example for which it does make a difference as a way to explain the
> two modes.

+1.


^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-10-26 18:30 ` Jim Porter
  2023-10-29 16:38   ` Richard Stallman
@ 2023-11-04  8:27   ` Eli Zaretskii
  2023-11-04 16:44     ` Jim Porter
  1 sibling, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2023-11-04  8:27 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Jim Porter, 66756

> Date: Thu, 26 Oct 2023 11:30:46 -0700
> From: Jim Porter <jporterbugs@gmail.com>
> 
> On 10/26/2023 12:09 AM, Eli Zaretskii wrote:
>  > Thanks.
>  >
>  > The challenge in updating the Lisp Introduction manual is to try to
>  > keep its informal and reader-friendly style as much as possible.  It
>  > is not just another ELisp Reference manual!  So please try to keep
>  > that in mind when you write the text, and in particular try not to
>  > modify the existing text that is still accurate -- it was written by a
>  > master, and each word there counts, even if it looks at first sight as
>  > not important.
> 
> Ok, here's a second attempt. I've tried to avoid changing anything that 
> I don't think is truly necessary. I did alter a bit of the original 
> wording to emphasize that under lexical binding, 'let' isn't about time, 
> but about place. For example, that's why I changed this:
> 
> > This is like understanding that whenever your host refers to ``the house'', he means his house, not yours.
> 
> to this:
> 
> > This is like understanding that in your host's home, whenever he refers to ``the house'', he means his house, not yours.
> 
> My previous concern about the "lexical binding" digression still applies 
> though. However, I'm not sure how to get around that at present; if we 
> want to talk about lexical binding in the manual, we need to get users 
> to enable it, so I think it's unavoidable that we at least mention it. I 
> tried to introduce the jargon as gently as I could (by first introducing 
> the term "binding" on its own before mentioning "lexical/dynamic 
> binding"), but it's still a bit intimidating. On the positive side, when 
> lexical binding is the default, we could remove that entire digression.
> 
> There's also an argument that the example I added is in the wrong spot, 
> since we haven't actually introduced the 'let' syntax yet. However, I 
> personally find the example to be pretty useful since it shows off one 
> of the key differences between lexical and dynamic binding, and helps 
> show one of the boundaries of the 'let' form's scope. I myself tend to 
> learn best by seeing examples of that sort. Fixing the order so we 
> introduce the syntax first would require more extensive changes to this 
> section...

Richard, could you please review these changes?

> From 12847e0d59b2de3791efa090addc0169e713e6d1 Mon Sep 17 00:00:00 2001
> From: Jim Porter <jporterbugs@gmail.com>
> 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
> (including how to enable it).
> ---
>  doc/lispintro/emacs-lisp-intro.texi | 67 ++++++++++++++++++++++-------
>  1 file changed, 51 insertions(+), 16 deletions(-)
> 
> diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
> index fce7583fe91..e805833f979 100644
> --- a/doc/lispintro/emacs-lisp-intro.texi
> +++ b/doc/lispintro/emacs-lisp-intro.texi
> @@ -3602,24 +3602,59 @@ Prevent confusion
>  @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 ``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.)
> +@cindex lexical binding
> +@cindex binding, lexical
> +@cindex dynamic binding
> +@cindex binding, dynamic
> +Before we begin discussing @code{let} in detail, we must first mention
> +an important note.  For historical reasons, Emacs Lisp uses a form of
> +variable binding called ``dynamic binding''.  However, this manual
> +will discuss the preferred form of binding, called ``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, you should add something like 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}.
> +
> +With that out of the way, we can get back to discussing @code{let}.
> +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.
> +
> +For example, 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
> +(setq x 1)
> +
> +(defun getx ()
> +  x)
> +
> +(let ((x 2))
> +  (get-x))
> +     @result{} 1
> +@end example
>  
>  @code{let} can create more than one variable at once.  Also,
>  @code{let} gives each variable it creates an initial value, either a
> -- 
> 2.25.1
> 





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-04  8:27   ` Eli Zaretskii
@ 2023-11-04 16:44     ` Jim Porter
  0 siblings, 0 replies; 33+ messages in thread
From: Jim Porter @ 2023-11-04 16:44 UTC (permalink / raw)
  To: Eli Zaretskii, Richard Stallman; +Cc: 66756

On 11/4/2023 1:27 AM, Eli Zaretskii wrote:
> Richard, could you please review these changes?

I see that there are already some good suggestions for how to improve my 
patch, so I'll try to work on that this weekend.






^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-10-26  5:54 bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual Jim Porter
  2023-10-26 18:30 ` Jim Porter
@ 2023-11-06  2:29 ` Richard Stallman
  2023-11-06  2:29 ` Richard Stallman
  2 siblings, 0 replies; 33+ messages in thread
From: Richard Stallman @ 2023-11-06  2:29 UTC (permalink / raw)
  To: Jim Porter; +Cc: 66756

[[[ 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. ]]]

This change is overall a step forward.  Thanks for working on it.

A few specific parts of the new text could use a little cleaning up;
some of those parts are in the current version also.

    +``scope'').  @code{let} creates a name for a @dfn{local variable} that
    +overshadows any use of the same name outside the @code{let} expression
    +(we call this ``binding'' the variable).

The word "overshadows" seems stramge here.  The usual term is "shadows",
and I don't see that "overshadows" adds any clarity.

  >   For historical reasons, Emacs Lisp uses a form of
  > +variable binding called ``dynamic binding''.

This should say "by default", because it isn't always so.  For
instance, if you specify lexical binding, then Emacs Lisp does not use
dynamic binding, except for variables marked special.

  > +lexical binding, you should add something like this to the first line

Delete "something like".



-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-10-26  5:54 bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual Jim Porter
  2023-10-26 18:30 ` Jim Porter
  2023-11-06  2:29 ` Richard Stallman
@ 2023-11-06  2:29 ` Richard Stallman
  2 siblings, 0 replies; 33+ messages in thread
From: Richard Stallman @ 2023-11-06  2:29 UTC (permalink / raw)
  To: Jim Porter; +Cc: 66756

[[[ 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. ]]]

  > +The @code{let} special form provides a way to confine your variables
  > +to a particular section of your code (in computer science jargon, a
  > +``scope'').  @code{let} creates a name for a @dfn{local variable} that
  > +overshadows any use of the same name outside the @code{let} expression
  > +(we call this ``binding'' the variable).  This prevents any accidental
  > +usage of these variables outside of the @code{let} expression.

This is one of several reasons to use `let'.

Others are

* To compute a value once and use it more than once.

* To create a loop index variable.

* For special variables, to bind them si as to control the behavior
of other code.

Should all of them be mentioned in this node?  I am not sure;
that is a pedagogical question.  But this node shouldn't assert
that one reason is the only reason.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-10-29 16:38   ` Richard Stallman
  2023-10-29 17:18     ` Drew Adams
@ 2023-11-18  2:09     ` Jim Porter
  2023-11-19  3:39       ` Richard Stallman
  1 sibling, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-11-18  2:09 UTC (permalink / raw)
  To: rms; +Cc: eliz, 66756

[-- Attachment #1: Type: text/plain, Size: 621 bytes --]

On 10/29/2023 9:38 AM, Richard Stallman wrote:
> So perhaps it is possible for the first few sections to use examples
> which work the same in lexical mode and dynamic mode, THEN show an
> example for which it does make a difference as a way to explain the
> two modes.

It took a bit longer for me to get back to this than I had hoped, but 
here's an updated patch. I've added a new subsection to the end that 
describes lexical vs dynamic binding, and tried to keep the "let 
Prevents Confusion" section as similar in spirit as I could to the 
original, while still updating the parts that change under lexical binding.

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 6087 bytes --]

From c972b0fbf52eb33eceb2b6547be418e6e64bc1f7 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
Date: Wed, 25 Oct 2023 20:43:57 -0700
Subject: [PATCH] Introduce 'let' using lexical binding in the Lisp
 Introduction

Bug#66756.

* 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).
---
 doc/lispintro/emacs-lisp-intro.texi | 95 +++++++++++++++++++++++------
 1 file changed, 78 insertions(+), 17 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index c5b33ac5eaa..4fa743326ef 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,69 @@ 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'' (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 1)
+
+(defun getx ()
+  x)
+
+(let ((x 2))
+  (getx))
+     @result{} 1
+@end example
+
+@noindent
+If we instead change @code{lexical-binding} to have a value of
+@code{nil}, we will get a different result here.  Now, the result of
+@samp{(getx)} is @samp{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.
+
 @node if
 @section The @code{if} Special Form
 @findex if
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-18  2:09     ` Jim Porter
@ 2023-11-19  3:39       ` Richard Stallman
  2023-11-19  5:25         ` Jim Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Stallman @ 2023-11-19  3:39 UTC (permalink / raw)
  To: Jim Porter; +Cc: eliz, 66756

[[[ 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. ]]]

I think your changes are good.

  > +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'' (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}.

Do we want to change the default some day to lexical binding:?  If so,
we should say so somewhere in this manual -- perhaps here, perhaps
elsewhere,

  > +If we instead change @code{lexical-binding} to have a value of
  > +@code{nil}, we will get a different result here.

"Get a different result" is vague -- it would be clearer if it said
concretely what will happen.

I suggest you show the dynamci situation in the same way you show the lexical
situation.  That will help people compare the two.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-19  3:39       ` Richard Stallman
@ 2023-11-19  5:25         ` Jim Porter
  2023-11-19  5:30           ` Jim Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-11-19  5:25 UTC (permalink / raw)
  To: rms; +Cc: eliz, 66756

[-- Attachment #1: Type: text/plain, Size: 1544 bytes --]

On 11/18/2023 7:39 PM, Richard Stallman wrote:
>    > +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'' (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}.
> 
> Do we want to change the default some day to lexical binding:?  If so,
> we should say so somewhere in this manual -- perhaps here, perhaps
> elsewhere,

I believe that's the goal, yes. I've added a note that the maintainers 
eventually plan on making lexical binding the default.

>    > +If we instead change @code{lexical-binding} to have a value of
>    > +@code{nil}, we will get a different result here.
> 
> "Get a different result" is vague -- it would be clearer if it said
> concretely what will happen.
> 
> I suggest you show the dynamci situation in the same way you show the lexical
> situation.  That will help people compare the two.

Done. I've also expanded the prose explanation at the end in order to 
re-emphasize the differences between the two.

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 6590 bytes --]

From f805ebf65dc218c7ae63251a357a4deaaf45d752 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
Date: Wed, 25 Oct 2023 20:43:57 -0700
Subject: [PATCH] Introduce 'let' using lexical binding in the Lisp
 Introduction

Bug#66756.

* 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).
---
 doc/lispintro/emacs-lisp-intro.texi | 115 ++++++++++++++++++++++++----
 1 file changed, 98 insertions(+), 17 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index c5b33ac5eaa..554ba4a7560 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,89 @@ 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 primarily 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 1)
+
+(defun getx ()
+  x)
+
+(let ((x 2))
+  (getx))
+     @result{} 1
+@end example
+
+@noindent
+If we use dynamic binding instead, the behavior is different:
+
+@example
+;;; -*- lexical-binding: nil -*-
+
+(setq x 1)
+
+(defun getx ()
+  x)
+
+(let ((x 2))
+  (getx))
+     @result{} 2
+@end example
+
+Now, the result of @samp{(getx)} is @samp{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.  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.
+
 @node if
 @section The @code{if} Special Form
 @findex if
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-19  5:25         ` Jim Porter
@ 2023-11-19  5:30           ` Jim Porter
  2023-11-19  8:38             ` Michael Albinus
  2023-11-23  2:57             ` Richard Stallman
  0 siblings, 2 replies; 33+ messages in thread
From: Jim Porter @ 2023-11-19  5:30 UTC (permalink / raw)
  To: rms; +Cc: eliz, 66756

[-- Attachment #1: Type: text/plain, Size: 269 bytes --]

On 11/18/2023 9:25 PM, Jim Porter wrote:
> I believe that's the goal, yes. I've added a note that the maintainers 
> eventually plan on making lexical binding the default.

Oops, I forgot to finish rewording one sentence in my previous patch. 
Here's the fixed version.

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 6580 bytes --]

From a1effe96de6c6ef1ec2d97e65ccb383de87022fd Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
Date: Wed, 25 Oct 2023 20:43:57 -0700
Subject: [PATCH] Introduce 'let' using lexical binding in the Lisp
 Introduction

Bug#66756.

* 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).
---
 doc/lispintro/emacs-lisp-intro.texi | 115 ++++++++++++++++++++++++----
 1 file changed, 98 insertions(+), 17 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index c5b33ac5eaa..53a51ed001d 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,89 @@ 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 1)
+
+(defun getx ()
+  x)
+
+(let ((x 2))
+  (getx))
+     @result{} 1
+@end example
+
+@noindent
+If we use dynamic binding instead, the behavior is different:
+
+@example
+;;; -*- lexical-binding: nil -*-
+
+(setq x 1)
+
+(defun getx ()
+  x)
+
+(let ((x 2))
+  (getx))
+     @result{} 2
+@end example
+
+Now, the result of @samp{(getx)} is @samp{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.  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.
+
 @node if
 @section The @code{if} Special Form
 @findex if
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-19  5:30           ` Jim Porter
@ 2023-11-19  8:38             ` Michael Albinus
  2023-11-19 20:17               ` Jim Porter
  2023-11-23  2:57             ` Richard Stallman
  1 sibling, 1 reply; 33+ messages in thread
From: Michael Albinus @ 2023-11-19  8:38 UTC (permalink / raw)
  To: Jim Porter; +Cc: eliz, rms, 66756

Jim Porter <jporterbugs@gmail.com> writes:

Hi Jim,

> +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 1)
> +
> +(defun getx ()
> +  x)
> +
> +(let ((x 2))
> +  (getx))
> +     @result{} 1
> +@end example
> +
> +@noindent
> +If we use dynamic binding instead, the behavior is different:
> +
> +@example
> +;;; -*- lexical-binding: nil -*-
> +
> +(setq x 1)
> +
> +(defun getx ()
> +  x)
> +
> +(let ((x 2))
> +  (getx))
> +     @result{} 2
> +@end example
> +
> +Now, the result of @samp{(getx)} is @samp{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.  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.

Would it be worth to emphasize, that a declaration of x changes this?
That is, when a variable is declared, both lexical and dynamic binding
behave identically.

@example
;;; -*- lexical-binding: t -*-

(devfar x 1)

(defun getx ()
  x)

(let ((x 2))
  (getx))
     @result{} 2
@end example

Best regards, Michael.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-19  8:38             ` Michael Albinus
@ 2023-11-19 20:17               ` Jim Porter
  2023-11-19 23:05                 ` Jim Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-11-19 20:17 UTC (permalink / raw)
  To: Michael Albinus; +Cc: eliz, rms, 66756

On 11/19/2023 12:38 AM, Michael Albinus wrote:
> Would it be worth to emphasize, that a declaration of x changes this?
> That is, when a variable is declared, both lexical and dynamic binding
> behave identically.

Thanks, that's probably a good idea. We should mention this in the 
section that introduces 'defvar'. I'll work on adding that.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-19 20:17               ` Jim Porter
@ 2023-11-19 23:05                 ` Jim Porter
  2023-11-20 13:28                   ` Michael Albinus
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-11-19 23:05 UTC (permalink / raw)
  To: Michael Albinus; +Cc: eliz, rms, 66756

[-- Attachment #1: Type: text/plain, Size: 516 bytes --]

On 11/19/2023 12:17 PM, Jim Porter wrote:
> On 11/19/2023 12:38 AM, Michael Albinus wrote:
>> Would it be worth to emphasize, that a declaration of x changes this?
>> That is, when a variable is declared, both lexical and dynamic binding
>> behave identically.
> 
> Thanks, that's probably a good idea. We should mention this in the 
> section that introduces 'defvar'. I'll work on adding that.

Ok, what about this? I just added a mention to the 'defvar' section 
about this, and cross-referenced the two sections.

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 8052 bytes --]

From 9db675656ea76a401a792a711231766b3d7a87d2 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
Date: Wed, 25 Oct 2023 20:43:57 -0700
Subject: [PATCH] Introduce 'let' using lexical binding in the Lisp
 Introduction

Bug#66756.

* 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.
---
 doc/lispintro/emacs-lisp-intro.texi | 133 +++++++++++++++++++++++-----
 1 file changed, 110 insertions(+), 23 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index c5b33ac5eaa..9a8b93fbd3e 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,93 @@ 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 1)
+
+(defun getx ()
+  x)
+
+(let ((x 2))
+  (getx))
+     @result{} 1
+@end example
+
+@noindent
+If we use dynamic binding instead, the behavior is different:
+
+@example
+;;; -*- lexical-binding: nil -*-
+
+(setq x 1)
+
+(defun getx ()
+  x)
+
+(let ((x 2))
+  (getx))
+     @result{} 2
+@end example
+
+Now, the result of @samp{(getx)} is @samp{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.  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.
+
+(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 +9215,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


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-19 23:05                 ` Jim Porter
@ 2023-11-20 13:28                   ` Michael Albinus
  0 siblings, 0 replies; 33+ messages in thread
From: Michael Albinus @ 2023-11-20 13:28 UTC (permalink / raw)
  To: Jim Porter; +Cc: eliz, rms, 66756

Jim Porter <jporterbugs@gmail.com> writes:

Hi Jim,

> Ok, what about this? I just added a mention to the 'defvar' section
> about this, and cross-referenced the two sections.

Looks OK to me. But perhaps Lisp language experts might have a look on
this also.

Best regards, Michael.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-19  5:30           ` Jim Porter
  2023-11-19  8:38             ` Michael Albinus
@ 2023-11-23  2:57             ` Richard Stallman
  2023-11-23 21:04               ` Jim Porter
  1 sibling, 1 reply; 33+ messages in thread
From: Richard Stallman @ 2023-11-23  2:57 UTC (permalink / raw)
  To: Jim Porter; +Cc: eliz, 66756

[[[ 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. ]]]

Your work is good.

After this,

  > +;;; -*- lexical-binding: t -*-
  > +
  > +(setq x 1)
  > +
  > +(defun getx ()
  > +  x)
  > +
  > +(let ((x 2))
  > +  (getx))
  > +     @result{} 1
  > +@end example

it could be good to add the following:

+(setq x 3)
+
+(let ((x 2))
+  (getx))
+     @result{} 3
+
+(setq x '(foo))
+
+(let ((x 2))
+  (getx))
+     @result{} (foo)
+@end example

to show that `getx' accesses the current value of the global binding,
not the value that the global binding had when getx was defined.

Adding this to the lexical binding example

+(setq x 3)
+
+(let ((x 2))
+  (getx))
+     @result{} 2
+
+(setq x '(foo))
+
+(let ((x 2))
+  (getx))
+     @result{} 2

could also help, by showing that changes in the global binding's value
are irrelevant for references to x where that binding is shadowed.

Or perhaps this pair of examples should be presented as a separate
point following the other one.
-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-23  2:57             ` Richard Stallman
@ 2023-11-23 21:04               ` Jim Porter
  2023-11-24  7:06                 ` Eli Zaretskii
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-11-23 21:04 UTC (permalink / raw)
  To: rms; +Cc: eliz, 66756

[-- Attachment #1: Type: text/plain, Size: 952 bytes --]

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.

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 8207 bytes --]

From fdfae219bec8255e173e8ef448f3b49de6fcc753 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
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


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-23 21:04               ` Jim Porter
@ 2023-11-24  7:06                 ` Eli Zaretskii
  2023-11-24  9:01                   ` Jim Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2023-11-24  7:06 UTC (permalink / raw)
  To: Jim Porter; +Cc: rms, 66756

> Date: Thu, 23 Nov 2023 13:04:01 -0800
> Cc: eliz@gnu.org, 66756@debbugs.gnu.org
> From: Jim Porter <jporterbugs@gmail.com>
> 
> @@ -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}.)

FWIW, I find the use of "overshadows" in the original text to be
better than the "overrides" in the new text.  This is partly because
the meaning of "override" is not clear when talking about the use of a
name, and partly because "override" is really inaccurate here.  If we
are not happy with the original text, then we need to find something
else, IMO, perhaps a more detailed description.

> +@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.

Markup note: each of the phrases quoted ``like this'' in this passage
should actually be a @dfn.

> +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.

If this wants to explain the difference between compile-time and
run-time binding, then perhaps it should say so, instead of talking
about the confusing "place where" vs "time when" the value changes?
And if compile-time is problematic (Emacs being an interpreter), then
we should find another description, one that doesn't use confusing
concept of "place".

IOW, I don't feel like reading this and the previous description of
'let' I understood the difference between lexical-binding and dynamic
binding.  One problem here is that, in an interpreted environment such
as Emacs Lisp, there's no well-defined notion of "compile-time", and
"time" is deterministically determined by "place".

> +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.

The immediate question I had when reading this is how is this
different from the lexical-binding rules.  Isn't the let-binding under
lexical-binding also "temporary and local"? isn't the value also
"undone when 'let' is finished? doesn't the setting only "affect the
expressions that are inside the bounds of 'let'"?

Can the text answer these questions?

> +@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}.

It is not really clear here what is meant by "place".  The code shows
3 "places" where x gets a value: the two 'setq's and the 'let'.  It is
left unexplained why 'getx' sees the 2nd place, but not the other two.
So something crucial is missing from this description.

> +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.

The last sentence should be rephrased.  As written, it states the
obvious: 'getx' is called inside of 'let'.  What it should say instead
is something that would explain why this "during the *time*" part
explains how dynamic binding works, perhaps talking about the last
time a variable gets its value in the run-time sequence of events.
The sentence before that should probably also rephrased accordingly.

> -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.

I wonder whether we should make the "second" part be the "first" one
here.

Thanks.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-24  7:06                 ` Eli Zaretskii
@ 2023-11-24  9:01                   ` Jim Porter
  2023-11-24 11:41                     ` Eli Zaretskii
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-11-24  9:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: rms, 66756

Thanks for taking a look, Eli. Just a few questions/thoughts on some of 
your comments. (I trimmed the others since I'll probably rework the 
other sections based on how we handle the second part below.)

On 11/23/2023 11:06 PM, Eli Zaretskii wrote:
> FWIW, I find the use of "overshadows" in the original text to be
> better than the "overrides" in the new text.  This is partly because
> the meaning of "override" is not clear when talking about the use of a
> name, and partly because "override" is really inaccurate here.  If we
> are not happy with the original text, then we need to find something
> else, IMO, perhaps a more detailed description.

Maybe we should just leave it as is for now? I don't think it's strictly 
necessary to change that sentence for the rest of the patch to make 
sense. We could always improve it in a follow up.

(Or if someone has the perfect phrase to use here, I'll happily make the 
change. I just don't want the patch to get bogged down by changes that 
are merely *near* the parts I'm working on.)

>> +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.
> 
> If this wants to explain the difference between compile-time and
> run-time binding, then perhaps it should say so, instead of talking
> about the confusing "place where" vs "time when" the value changes?
> And if compile-time is problematic (Emacs being an interpreter), then
> we should find another description, one that doesn't use confusing
> concept of "place".

I'm open to other wordings, but I wanted to describe what's going on 
without getting into the details of the interpreter or how it evaluates 
the code. The "place" is supposed to refer to the actual body of the 
'let' form. That's described in the first part I changed. However, the 
"time" description could probably be expanded.

Maybe we could contrast "within the body of the let expression" vs 
"during execution of the let expression"? That gets across the idea to 
me that the former is about compile-time ("body" refers to the actual 
Lisp form), while the latter is about run-time ("execution").





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-24  9:01                   ` Jim Porter
@ 2023-11-24 11:41                     ` Eli Zaretskii
  2023-11-24 21:46                       ` Jim Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2023-11-24 11:41 UTC (permalink / raw)
  To: Jim Porter; +Cc: rms, 66756

> Date: Fri, 24 Nov 2023 01:01:33 -0800
> Cc: rms@gnu.org, 66756@debbugs.gnu.org
> From: Jim Porter <jporterbugs@gmail.com>
> 
> >> +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.
> > 
> > If this wants to explain the difference between compile-time and
> > run-time binding, then perhaps it should say so, instead of talking
> > about the confusing "place where" vs "time when" the value changes?
> > And if compile-time is problematic (Emacs being an interpreter), then
> > we should find another description, one that doesn't use confusing
> > concept of "place".
> 
> I'm open to other wordings, but I wanted to describe what's going on 
> without getting into the details of the interpreter or how it evaluates 
> the code. The "place" is supposed to refer to the actual body of the 
> 'let' form. That's described in the first part I changed. However, the 
> "time" description could probably be expanded.
> 
> Maybe we could contrast "within the body of the let expression" vs 
> "during execution of the let expression"? That gets across the idea to 
> me that the former is about compile-time ("body" refers to the actual 
> Lisp form), while the latter is about run-time ("execution").

"During the execution" is probably a good idea, but "within the body
of the expression" Does not seem to contrast with that, since it also
holds for dynamic binding.

I think the explanation should focus on the code of getx, not on the
code in the 'let'-form's body.  The reason for what happens under
lexical binding is in getx.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-24 11:41                     ` Eli Zaretskii
@ 2023-11-24 21:46                       ` Jim Porter
  2023-11-25  7:51                         ` Eli Zaretskii
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-11-24 21:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: rms, 66756

[-- Attachment #1: Type: text/plain, Size: 907 bytes --]

On 11/24/2023 3:41 AM, Eli Zaretskii wrote:
> "During the execution" is probably a good idea, but "within the body
> of the expression" Does not seem to contrast with that, since it also
> holds for dynamic binding.

For "within the body of the expression", I wanted a phrase I could use 
near the beginning of this discussion, before we get into the 
differences of lexical vs dynamic binding. That way, I can refer back to 
it in the lexical/dynamic binding section and contrast it with the 
dynamic binding definition.

I've added some more explanation to it though, so hopefully that helps 
clarify things. I also reworked the description of dynamic binding to 
talk about how each variable has a stack of bindings. Hopefully this is 
clear enough; I think it's more straightforward than the previous one, 
since it uses a stack of papers on one's desk as a visual analogy to 
help drive the point home.

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 8918 bytes --]

From 9800c1458ffa33780c2763dbd3013efad1b2dbd8 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
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 | 157 +++++++++++++++++++++++-----
 1 file changed, 133 insertions(+), 24 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index c5b33ac5eaa..edcb41ed796 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
@@ -3602,24 +3603,22 @@ Prevent confusion
 @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.
-@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.)
+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.  (Symbols used in argument lists work the
+same way.  @xref{defun, , The @code{defun} Macro}.)
+
+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).  In practice, 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, 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 +3778,114 @@ 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 @dfn{scope}).  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}.
+
+As we discussed before, 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 in the
+@code{let} body, that function would be unable to ``see'' the local
+variables you've created.
+
+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 let expression.  This means that, if your @code{let}
+expression calls a function, that function can see (and modify) these
+local variables.
+
+Another way to think about @code{let} when using dynamic binding is
+that every variable name has a ``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 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.
+
+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.  Instead, @code{getx} looks for @code{x}
+elsewhere, and finds it at the global scope of our code.  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
+
+@noident
+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} 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
@@ -9130,12 +9237,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 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}.
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-24 21:46                       ` Jim Porter
@ 2023-11-25  7:51                         ` Eli Zaretskii
  2023-11-30 21:03                           ` Jim Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2023-11-25  7:51 UTC (permalink / raw)
  To: Jim Porter; +Cc: rms, 66756

> Date: Fri, 24 Nov 2023 13:46:55 -0800
> Cc: rms@gnu.org, 66756@debbugs.gnu.org
> From: Jim Porter <jporterbugs@gmail.com>
> 
> +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).  In practice, 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, calling @code{setq} for a
> +variable named by the @code{let} expression will @emph{not} affect
> +that local variable.

I think something is missing from this description: "inside the 'let'
body" is ambiguous when the body calls functions.  The text should
explain that the body of functions called from 'let' is NOT considered
to be "inside the 'let' body".  This crucial point is hinted or
explained later, but it must be explained right here at the start.

> +As we discussed before, 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 in the
> +@code{let} body, that function would be unable to ``see'' the local
> +variables you've created.

First, AFAIU the last sentence is correct only if the function's
definition is outside of the 'let'.  And second, this crucial
dependence on where the function is defined is very important for
understanding _why_ the function won't see the value bound by 'let'.
So it must be in the text, IMO.

> +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 let expression.  This means that, if your @code{let}
> +expression calls a function, that function can see (and modify) these
> +local variables.

This should say "...regardless of where the function is defined."  I
would even add that the above is true even for functions defined on
other Lisp files.

> +Another way to think about @code{let} when using dynamic binding is
> +that every variable name has a ``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 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.

This should IMO tell that this "binding stack" is _global_, i.e. it is
seen by every function regardless of where and how it was defined.

> +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.

The last sentence is critical for understanding of the issue, and
should be at the very beginning of the 'let' description (and repeated
here, of course).

>                          Instead, @code{getx} looks for @code{x}
> +elsewhere, and finds it at the global scope of our code.

This "looks for and finds" is problematic, IMO, because it is not
clear why would it "find" the value of x set by 'setq', but not the
value of x set by 'let'.  IOW, the mechanism of "looking and finding"
remains mysterious and no intuitive description is provided to help
understanding it.  Can we provide such a description?  If you cannot
think about one, how about explaining the internal workings of this
"looking and finding" as it is implemented, and we could then take it
from there and express the idea in less technical ways.

> +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} 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.

This should mention the stack and its top earlier, where it talks
about "the current binding".

Thanks.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-25  7:51                         ` Eli Zaretskii
@ 2023-11-30 21:03                           ` Jim Porter
  2023-12-01  8:29                             ` Eli Zaretskii
                                               ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Jim Porter @ 2023-11-30 21:03 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: rms, 66756

[-- Attachment #1: Type: text/plain, Size: 4099 bytes --]

On 11/24/2023 11:51 PM, Eli Zaretskii wrote:
> I think something is missing from this description: "inside the 'let'
> body" is ambiguous when the body calls functions.  The text should
> explain that the body of functions called from 'let' is NOT considered
> to be "inside the 'let' body".  This crucial point is hinted or
> explained later, but it must be explained right here at the start.

I added a short parenthetical here to explain this point: "(such as when 
calling a function that was defined elsewhere)". I intentionally kept 
this brief though, since this introductory section is primarily about 
introducing the basics of 'let' and why you'd use it. Once we've shown 
readers *how* to use 'let', then we return to a more detailed discussion 
of how the binding works in the last section.

>> +As we discussed before, 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 in the
>> +@code{let} body, that function would be unable to ``see'' the local
>> +variables you've created.
> 
> First, AFAIU the last sentence is correct only if the function's
> definition is outside of the 'let'.  And second, this crucial
> dependence on where the function is defined is very important for
> understanding _why_ the function won't see the value bound by 'let'.
> So it must be in the text, IMO.

I've expanded upon this and added a description of what happens when you 
call a function defined within a 'let' body.

>> +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 let expression.  This means that, if your @code{let}
>> +expression calls a function, that function can see (and modify) these
>> +local variables.
> 
> This should say "...regardless of where the function is defined."  I
> would even add that the above is true even for functions defined on
> other Lisp files.

Done.

> This should IMO tell that this "binding stack" is _global_, i.e. it is
> seen by every function regardless of where and how it was defined.

Done.

>> +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.
> 
> The last sentence is critical for understanding of the issue, and
> should be at the very beginning of the 'let' description (and repeated
> here, of course).

Done.

>>                           Instead, @code{getx} looks for @code{x}
>> +elsewhere, and finds it at the global scope of our code.
> 
> This "looks for and finds" is problematic, IMO, because it is not
> clear why would it "find" the value of x set by 'setq', but not the
> value of x set by 'let'.  IOW, the mechanism of "looking and finding"
> remains mysterious and no intuitive description is provided to help
> understanding it.  Can we provide such a description?  If you cannot
> think about one, how about explaining the internal workings of this
> "looking and finding" as it is implemented, and we could then take it
> from there and express the idea in less technical ways.

I've reworded this to hopefully be more explicit that, since 'getx' is 
defined outside of any 'let' body, it will look for 'x' at global scope. 
Combined with the previous, more-general discussion of how 'let' and 
'defun' interact, I think (hope) this should cover things.

>> +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} 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.
> 
> This should mention the stack and its top earlier, where it talks
> about "the current binding".

Done.

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 9310 bytes --]

From 8c416b752a87bc9226eeaad0399a3679985825a9 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
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 | 161 +++++++++++++++++++++++-----
 1 file changed, 137 insertions(+), 24 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index c5b33ac5eaa..caf9a3c876c 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
@@ -3602,24 +3603,22 @@ Prevent confusion
 @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.
-@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.)
+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.  (Symbols used in argument lists work the
+same way.  @xref{defun, , The @code{defun} Macro}.)
+
+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.
 
 @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 +3778,118 @@ 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 validscop.  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}.
+
+As we discussed before, 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 defined within a @code{let} body, that function
+@emph{would} be able to see---and modify---the local variables from
+that @code{let} expression.)
+
+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 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
+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.
+
+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
@@ -9130,12 +9241,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 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}.
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-30 21:03                           ` Jim Porter
@ 2023-12-01  8:29                             ` Eli Zaretskii
  2023-12-04  3:08                               ` Richard Stallman
  2023-12-04  3:08                             ` Richard Stallman
  2023-12-04  3:08                             ` Richard Stallman
  2 siblings, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2023-12-01  8:29 UTC (permalink / raw)
  To: Jim Porter, Richard Stallman; +Cc: 66756

> Date: Thu, 30 Nov 2023 13:03:52 -0800
> Cc: rms@gnu.org, 66756@debbugs.gnu.org
> From: Jim Porter <jporterbugs@gmail.com>
> 
> Done.

Thanks, I'm happy with this text now.

Richard, would you please read the latest patch posted by Jim and
comment on it?





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-30 21:03                           ` Jim Porter
  2023-12-01  8:29                             ` Eli Zaretskii
@ 2023-12-04  3:08                             ` Richard Stallman
  2023-12-04  4:34                               ` Jim Porter
  2023-12-04  3:08                             ` Richard Stallman
  2 siblings, 1 reply; 33+ messages in thread
From: Richard Stallman @ 2023-12-04  3:08 UTC (permalink / raw)
  To: Jim Porter; +Cc: eliz, 66756

[[[ 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. ]]]

  > +means his house, not yours.  (Symbols used in argument lists work the
  > +same way.

Maybe that sentence should be more explicit about which symbols it
refers to and which aspect of "working".  Perhaps like this:

   (The symbols used to name function arguments are bound as local variables
   in exactly the same way.)

This statement

      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.

is true only in lexical binding.  With dynamic binding, such a setq
_will_ set the let's local variable (in the simplest cases).

    +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 validscop.

Typo there.

    +As we discussed before, when you create local variables with
    +@code{let} under lexical binding, those variables are valid only
    +within the body of the @code{let} expression.

Where is this previous discussion?  I don't see it.  The distinction
of dynamic vs lexical was first introduced two paragraphs above,
and its effects on binding have not been discussed yet.

Is this a reference to the following?

      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.

That may be meant as a discussion of local binding with lexical scoping,
but it isn't one, since it doesn't say "lexical scoping."

      (On the other hand, if
    +you call a function defined within a @code{let} body,

I recommend "that was defined within"; it is more clear.

    +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 let expression.

@code needed here.

      When you bind a variable
    +with @code{let}, it puts the new binding you've specified on the top
    +of the stack,

For clarity, I suggest "bind a variable dynamically" or something to reiterate
that this sentence is only about dynamic binding.  Without that, the reader
could take it to be independent of which mode is currently selected.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-11-30 21:03                           ` Jim Porter
  2023-12-01  8:29                             ` Eli Zaretskii
  2023-12-04  3:08                             ` Richard Stallman
@ 2023-12-04  3:08                             ` Richard Stallman
  2 siblings, 0 replies; 33+ messages in thread
From: Richard Stallman @ 2023-12-04  3:08 UTC (permalink / raw)
  To: Jim Porter; +Cc: eliz, 66756

[[[ 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. ]]]

The new node How let Binds Variables is 110 lines long.  Such a long
node is cumbersome, especially for cross-references to it.

Can you find a way to subdivide it into smaller nodes?

It could have some text at the beginning, then a few subnodes.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-12-01  8:29                             ` Eli Zaretskii
@ 2023-12-04  3:08                               ` Richard Stallman
  0 siblings, 0 replies; 33+ messages in thread
From: Richard Stallman @ 2023-12-04  3:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jporterbugs, 66756

[[[ 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. ]]]

  > Richard, would you please read the latest patch posted by Jim and
  > comment on it?

Thanks for suggesting I do that.  I've sent my comments now.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-12-04  3:08                             ` Richard Stallman
@ 2023-12-04  4:34                               ` Jim Porter
  2023-12-10 19:36                                 ` Jim Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-12-04  4:34 UTC (permalink / raw)
  To: rms; +Cc: eliz, 66756

[-- Attachment #1: Type: text/plain, Size: 4118 bytes --]

On 12/3/2023 7:08 PM, Richard Stallman wrote:
> [[[ 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. ]]]
> 
>    > +means his house, not yours.  (Symbols used in argument lists work the
>    > +same way.
> 
> Maybe that sentence should be more explicit about which symbols it
> refers to and which aspect of "working".  Perhaps like this:
> 
>     (The symbols used to name function arguments are bound as local variables
>     in exactly the same way.)

Makes sense to me. Done.

> This statement
> 
>        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.
> 
> is true only in lexical binding.  With dynamic binding, such a setq
> _will_ set the let's local variable (in the simplest cases).

Correct. Based on Eli's suggestions, I've worded this initial section to 
assume that lexical binding is in effect. I put a footnote here to 
mention this, but otherwise I'm trying my hardest to avoid front-loading 
the 'let' documentation with an explanation of lexical binding.

>      +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 validscop.
> 
> Typo there.

Thanks. I think that was a mistake from when I was searching for "scope" 
to ensure I didn't inadvertently use the term in this section. (I wanted 
to avoid mentioning another CS term here, and I think "binding" is 
enough for what we want to say.)

>      +As we discussed before, when you create local variables with
>      +@code{let} under lexical binding, those variables are valid only
>      +within the body of the @code{let} expression.
> 
> Where is this previous discussion?  I don't see it.  The distinction
> of dynamic vs lexical was first introduced two paragraphs above,
> and its effects on binding have not been discussed yet.
> 
> Is this a reference to the following?
> 
>        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.
> 
> That may be meant as a discussion of local binding with lexical scoping,
> but it isn't one, since it doesn't say "lexical scoping."

Correct. I added a cross-reference back to that section. With that and 
the footnote in the "let Prevents Confusion" section, hopefully this is 
clearer now.

>        (On the other hand, if
>      +you call a function defined within a @code{let} body,
> 
> I recommend "that was defined within"; it is more clear.

Done.

>      +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 let expression.
> 
> @code needed here.

Fixed.

>        When you bind a variable
>      +with @code{let}, it puts the new binding you've specified on the top
>      +of the stack,
> 
> For clarity, I suggest "bind a variable dynamically" or something to reiterate
> that this sentence is only about dynamic binding.  Without that, the reader
> could take it to be independent of which mode is currently selected.

Done.

On 12/3/2023 7:08 PM, Richard Stallman wrote:
> The new node How let Binds Variables is 110 lines long.  Such a long
> node is cumbersome, especially for cross-references to it.
> 
> Can you find a way to subdivide it into smaller nodes?
> 
> It could have some text at the beginning, then a few subnodes.

I've split this into a main section and two subnodes: one describing how 
lexical and dynamic binding work, and one showing an example of how they 
behave differently in practice. Maybe the titles could be improved, but 
they're the best I could come up with at the time...

[-- Attachment #2: 0001-Introduce-let-using-lexical-binding-in-the-Lisp-Intr.patch --]
[-- Type: text/plain, Size: 9827 bytes --]

From 037a3578815dbaed71ea90ebc9598682fb159e23 Mon Sep 17 00:00:00 2001
From: Jim Porter <jporterbugs@gmail.com>
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 | 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 c5b33ac5eaa..4565b6c0ff0 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
@@ -3602,24 +3603,26 @@ Prevent confusion
 @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
@@ -3779,6 +3782,128 @@ 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
+
+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
@@ -9130,12 +9255,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 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}.
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-12-04  4:34                               ` Jim Porter
@ 2023-12-10 19:36                                 ` Jim Porter
  2023-12-16 23:10                                   ` Stefan Kangas
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-12-10 19:36 UTC (permalink / raw)
  To: rms; +Cc: eliz, 66756

On 12/3/2023 8:34 PM, Jim Porter wrote:
> I've split this into a main section and two subnodes: one describing how 
> lexical and dynamic binding work, and one showing an example of how they 
> behave differently in practice. Maybe the titles could be improved, but 
> they're the best I could come up with at the time...

Does anyone have any further comments on this patch? If not, I'll merge 
it into the master branch in the next few days. (Of course, we can 
always improve it more after merging if someone has a suggestion.)





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-12-10 19:36                                 ` Jim Porter
@ 2023-12-16 23:10                                   ` Stefan Kangas
  2023-12-17 20:47                                     ` Jim Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Stefan Kangas @ 2023-12-16 23:10 UTC (permalink / raw)
  To: Jim Porter, rms; +Cc: eliz, 66756

Jim Porter <jporterbugs@gmail.com> writes:

> On 12/3/2023 8:34 PM, Jim Porter wrote:
>> I've split this into a main section and two subnodes: one describing how
>> lexical and dynamic binding work, and one showing an example of how they
>> behave differently in practice. Maybe the titles could be improved, but
>> they're the best I could come up with at the time...
>
> Does anyone have any further comments on this patch? If not, I'll merge
> it into the master branch in the next few days. (Of course, we can
> always improve it more after merging if someone has a suggestion.)

I suggest merging it to emacs-29.  If we indeed think it's better, let's
get the improved documentation into users' hands.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-12-16 23:10                                   ` Stefan Kangas
@ 2023-12-17 20:47                                     ` Jim Porter
  2024-01-09 18:40                                       ` Jim Porter
  0 siblings, 1 reply; 33+ messages in thread
From: Jim Porter @ 2023-12-17 20:47 UTC (permalink / raw)
  To: Stefan Kangas, rms; +Cc: eliz, 66756

On 12/16/2023 3:10 PM, Stefan Kangas wrote:
> Jim Porter <jporterbugs@gmail.com> writes:
> 
>> Does anyone have any further comments on this patch? If not, I'll merge
>> it into the master branch in the next few days. (Of course, we can
>> always improve it more after merging if someone has a suggestion.)
> 
> I suggest merging it to emacs-29.  If we indeed think it's better, let's
> get the improved documentation into users' hands.

Sounds good to me. I'll give people another day or two to raise any last 
concerns, and if there aren't any, I'll merge to the 29 branch.





^ permalink raw reply	[flat|nested] 33+ messages in thread

* bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
  2023-12-17 20:47                                     ` Jim Porter
@ 2024-01-09 18:40                                       ` Jim Porter
  0 siblings, 0 replies; 33+ messages in thread
From: Jim Porter @ 2024-01-09 18:40 UTC (permalink / raw)
  To: Stefan Kangas, rms; +Cc: eliz, 66756-done

Version: 29.2

On 12/17/2023 12:47 PM, Jim Porter wrote:
> On 12/16/2023 3:10 PM, Stefan Kangas wrote:
>> Jim Porter <jporterbugs@gmail.com> writes:
>>
>> I suggest merging it to emacs-29.  If we indeed think it's better, let's
>> get the improved documentation into users' hands.
> 
> Sounds good to me. I'll give people another day or two to raise any last 
> concerns, and if there aren't any, I'll merge to the 29 branch.

I've now merged the latest revision of my patch to the release branch as 
d58d0fa52ff. Closing this bug.

Of course, if anyone sees any further issues, just let me know and I'll 
try to address them.





^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2024-01-09 18:40 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-26  5:54 bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual Jim Porter
2023-10-26 18:30 ` Jim Porter
2023-10-29 16:38   ` Richard Stallman
2023-10-29 17:18     ` Drew Adams
2023-11-18  2:09     ` Jim Porter
2023-11-19  3:39       ` Richard Stallman
2023-11-19  5:25         ` Jim Porter
2023-11-19  5:30           ` Jim Porter
2023-11-19  8:38             ` Michael Albinus
2023-11-19 20:17               ` Jim Porter
2023-11-19 23:05                 ` Jim Porter
2023-11-20 13:28                   ` Michael Albinus
2023-11-23  2:57             ` Richard Stallman
2023-11-23 21:04               ` Jim Porter
2023-11-24  7:06                 ` Eli Zaretskii
2023-11-24  9:01                   ` Jim Porter
2023-11-24 11:41                     ` Eli Zaretskii
2023-11-24 21:46                       ` Jim Porter
2023-11-25  7:51                         ` Eli Zaretskii
2023-11-30 21:03                           ` Jim Porter
2023-12-01  8:29                             ` Eli Zaretskii
2023-12-04  3:08                               ` Richard Stallman
2023-12-04  3:08                             ` Richard Stallman
2023-12-04  4:34                               ` Jim Porter
2023-12-10 19:36                                 ` Jim Porter
2023-12-16 23:10                                   ` Stefan Kangas
2023-12-17 20:47                                     ` Jim Porter
2024-01-09 18:40                                       ` Jim Porter
2023-12-04  3:08                             ` Richard Stallman
2023-11-04  8:27   ` Eli Zaretskii
2023-11-04 16:44     ` Jim Porter
2023-11-06  2:29 ` Richard Stallman
2023-11-06  2:29 ` Richard Stallman

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.