unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Eli Zaretskii <eliz@gnu.org>
To: Jim Porter <jporterbugs@gmail.com>
Cc: rms@gnu.org, 66756@debbugs.gnu.org
Subject: bug#66756: 30.0.50; [PATCH] Improve discussion of 'let' in Elisp Introduction manual
Date: Fri, 24 Nov 2023 09:06:11 +0200	[thread overview]
Message-ID: <83jzq7fx5o.fsf@gnu.org> (raw)
In-Reply-To: <9239b6bd-b476-b6c1-aef9-245e439aee42@gmail.com> (message from Jim Porter on Thu, 23 Nov 2023 13:04:01 -0800)

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





  reply	other threads:[~2023-11-24  7:06 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=83jzq7fx5o.fsf@gnu.org \
    --to=eliz@gnu.org \
    --cc=66756@debbugs.gnu.org \
    --cc=jporterbugs@gmail.com \
    --cc=rms@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).