all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Is this a bug in while-let or do I missunderstand it?
@ 2024-11-08 16:25 arthur miller
  2024-11-08 19:23 ` Philip Kaludercic
  2024-11-09  9:29 ` Yuri Khan
  0 siblings, 2 replies; 34+ messages in thread
From: arthur miller @ 2024-11-08 16:25 UTC (permalink / raw)
  To: emacs-devel@gnu.org

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

(progn
  (while-let ((run t))
    (message "Running")
    (setf run nil))
  (message "out of loop"))

It ends in infinite recursion. setf/setq have no effect on the lexical variable.

I tooka look, but I don't understand why is it necessary to build while-let  on
if-let. This simplified version did it for me:

(defmacro while-let (spec &rest body)
  "Bind variables according to SPEC and conditionally evaluate BODY.
Evaluate each binding in turn, stopping if a binding value is nil.
If all bindings are non-nil, eval BODY and repeat.

The variable list SPEC is the same as in `if-let*'."
  (declare (indent 1) (debug if-let))
  (let* ((bindings (if (and (consp spec) (symbolp (car spec)))
                           (list spec)
                         spec))
         (variables (mapcar #'car bindings)))
    `(let* ,bindings
       (while (and ,@variables)
         ,@body))))

(progn
  (while-let ((run t))
    (message "Running")
    (setf run nil))
  (message "out of loop"))  => "out of loop"

Or did I missunderstood how to use while-let in subr.el?

[-- Attachment #2: Type: text/html, Size: 5636 bytes --]

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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-08 16:25 arthur miller
@ 2024-11-08 19:23 ` Philip Kaludercic
  2024-11-09  9:29 ` Yuri Khan
  1 sibling, 0 replies; 34+ messages in thread
From: Philip Kaludercic @ 2024-11-08 19:23 UTC (permalink / raw)
  To: arthur miller; +Cc: emacs-devel@gnu.org

arthur miller <arthur.miller@live.com> writes:

> (progn
>   (while-let ((run t))
>     (message "Running")
>     (setf run nil))
>   (message "out of loop"))
>
> It ends in infinite recursion. setf/setq have no effect on the lexical variable.
>
> I tooka look, but I don't understand why is it necessary to build while-let  on
> if-let. This simplified version did it for me:
>
> (defmacro while-let (spec &rest body)
>   "Bind variables according to SPEC and conditionally evaluate BODY.
> Evaluate each binding in turn, stopping if a binding value is nil.
> If all bindings are non-nil, eval BODY and repeat.
>
> The variable list SPEC is the same as in `if-let*'."
>   (declare (indent 1) (debug if-let))
>   (let* ((bindings (if (and (consp spec) (symbolp (car spec)))
>                            (list spec)
>                          spec))
>          (variables (mapcar #'car bindings)))
>     `(let* ,bindings
>        (while (and ,@variables)
>          ,@body))))

With `if-let*' or `while-let' you want to have a sequence of
computations that are evaluated in order (either once for `if-let*' or
for every iteration in the case of `while-let'), until at least one
evaluates to nil.  All subsequent bindings shouldn't be evaluated, as
would be the case with your version of the macro.

> (progn
>   (while-let ((run t))
>     (message "Running")
>     (setf run nil))
>   (message "out of loop"))  => "out of loop"
>
> Or did I missunderstood how to use while-let in subr.el?

-- 
	Philip Kaludercic on siskin



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-08 16:25 arthur miller
  2024-11-08 19:23 ` Philip Kaludercic
@ 2024-11-09  9:29 ` Yuri Khan
  2024-11-09 13:03   ` Sv: " arthur miller
  1 sibling, 1 reply; 34+ messages in thread
From: Yuri Khan @ 2024-11-09  9:29 UTC (permalink / raw)
  To: arthur miller; +Cc: emacs-devel@gnu.org

On Sat, 9 Nov 2024 at 01:44, arthur miller <arthur.miller@live.com> wrote:
>
> (progn
>   (while-let ((run t))
>     (message "Running")
>     (setf run nil))
>   (message "out of loop"))
>
> It ends in infinite recursion. setf/setq have no effect on the lexical variable.

Probably not infinite recursion but infinite loop.

Why would you expect anything else? ‘while-let’ is documented as:

    Bind variables according to SPEC and conditionally evaluate BODY.
    Evaluate each binding in turn, stopping if a binding value is nil.
    If all bindings are non-nil, eval BODY and repeat.

In your case, the sequence is:

1. Evaluate the expression ‘t’ in the first (and only) binding. This yields ‘t’.
2. Bind the result of step 1, ‘t’, to local variable ‘run’.
3. Check if ‘run’ is nil. It isn’t, so proceed to step 4.
4. There are no more bindings. Run the body.
4a. Evaluate ‘(message "Running")’.
4b. Evaluate ‘(setf run nil)’. This changes the value of ‘run’ to nil.
5. Repeat from step 1.

Re-evaluating every binding’s expression is expected. Consider this usage:

    (while-let ((values-to-process (get-values)))
      (while values-to-process
        (setq value (pop values-to-process))
        (process value)))

At the end of each outer loop’s iteration, ‘values-to-process’ is nil,
but you don’t want to break out of the outer loop immediately, you
want to check if there is more work to do.



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 13:03   ` Sv: " arthur miller
@ 2024-11-09 13:15     ` Yuri Khan
  2024-11-09 13:38       ` Sv: " arthur miller
  0 siblings, 1 reply; 34+ messages in thread
From: Yuri Khan @ 2024-11-09 13:15 UTC (permalink / raw)
  To: arthur miller; +Cc: emacs-devel@gnu.org

On Sat, 9 Nov 2024 at 20:03, arthur miller <arthur.miller@live.com> wrote:
>
> >> (progn
> >>   (while-let ((run t))
> >>     (message "Running")
> >>     (setf run nil))
> >>   (message "out of loop"))
> >>
> >> It ends in infinite recursion. setf/setq have no effect on the lexical variable.
> >
> >Probably not infinite recursion but infinite loop.
> >
> >Why would you expect anything else? ‘while-let’ is documented as:
> >
> >    Bind variables according to SPEC and conditionally evaluate BODY.
>
> What should I expect?
>
> It does not says *read-only bindings*, it says bindings. Is it
> unreasonable to store a value in an established lexical binding?

I expect the binding is writable *but* it gets re-assigned on each iteration.

> (progn
>   (let ((run t))
>     (while run
>       (message "running")
>       (setf run nil))
>     (message "not running")))
>
> That is what I expect while-let to be equivalent to.

This is what I expect:

    (progn
      (let ((run))
        (while (setf run t)
          (message "running")
          (setf run nil)       ; useless because ‘run’ will be
reassigned right next
        )
      (message "not running")  ; unreachable
    )



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 13:38       ` Sv: " arthur miller
@ 2024-11-09 13:41         ` Yuri Khan
  2024-11-09 13:47           ` Sv: " arthur miller
  0 siblings, 1 reply; 34+ messages in thread
From: Yuri Khan @ 2024-11-09 13:41 UTC (permalink / raw)
  To: arthur miller; +Cc: emacs-devel@gnu.org

On Sat, 9 Nov 2024 at 20:38, arthur miller <arthur.miller@live.com> wrote:

> >I expect the binding is writable *but* it gets re-assigned on each iteration.
>
> Yes.
> I have already posted the macro expansions in respone to Phillip.
> It is quite clear what is going on. I think it is a bug, or at
> least very unintuitive behaviour.

Why? Pretty much all implementations of the ‘while’ loop in all
languages I’ve seen re-evaluate the condition on every iteration.



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 13:47           ` Sv: " arthur miller
@ 2024-11-09 14:04             ` Yuri Khan
  2024-11-09 16:33               ` Alfred M. Szmidt
  2024-11-09 21:47             ` Sv: " Joost Kremers
  1 sibling, 1 reply; 34+ messages in thread
From: Yuri Khan @ 2024-11-09 14:04 UTC (permalink / raw)
  To: arthur miller; +Cc: emacs-devel@gnu.org

On Sat, 9 Nov 2024 at 20:47, arthur miller <arthur.miller@live.com> wrote:

> If it wasn't clear, the unintuitive part is that while-let was to
> establish the local environment, so that we don't need to type:
>
> (let ((som-var (init-form)))
>     (while some-var
>         ... ))

But if it did it that way, the condition (init-form) would only be
evaluated once, and I’d find *that* counterintuitive. Consider the
usual form of a while loop:

    (while-let ((run (some-condition)))
      (message "running"))

Do you expect that to evaluate (some-condition) once, then, if it’s
initially true, run forever?



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 14:04             ` Yuri Khan
@ 2024-11-09 16:33               ` Alfred M. Szmidt
  2024-11-09 16:44                 ` Eli Zaretskii
  2024-11-09 20:29                 ` Sv: " arthur miller
  0 siblings, 2 replies; 34+ messages in thread
From: Alfred M. Szmidt @ 2024-11-09 16:33 UTC (permalink / raw)
  To: Yuri Khan; +Cc: arthur.miller, emacs-devel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1442 bytes --]

   > If it wasn't clear, the unintuitive part is that while-let was to
   > establish the local environment, so that we don't need to type:
   >
   > (let ((som-var (init-form)))
   >     (while some-var
   >         ... ))

   But if it did it that way, the condition (init-form) would only be
   evaluated once, and I’d find *that* counterintuitive. Consider the
   usual form of a while loop:

       (while-let ((run (some-condition)))
	 (message "running"))

   Do you expect that to evaluate (some-condition) once, then, if it’s
   initially true, run forever?

That is how it is described in the manual, so yes (some-condition)
should only be done once, and not every iteration.  See (elisp)
Conditionals .

      It can be convenient to bind variables in conjunction with using a
   conditional.  It's often the case that you compute a value, and then
   want to do something with that value if it's non-‘nil’.  The
   straightforward way to do that is to just write, for instance:
   
        (let ((result1 (do-computation)))
          (when result1
            (let ((result2 (do-more result1)))
              (when result2
                (do-something result2)))))

      Since this is a very common pattern, Emacs provides a number of
   macros to make this easier and more readable.  The above can be written
   the following way instead:

... following the various with various FOO-let forms, ending with
while-let.



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 16:33               ` Alfred M. Szmidt
@ 2024-11-09 16:44                 ` Eli Zaretskii
  2024-11-09 16:53                   ` Eli Zaretskii
                                     ` (2 more replies)
  2024-11-09 20:29                 ` Sv: " arthur miller
  1 sibling, 3 replies; 34+ messages in thread
From: Eli Zaretskii @ 2024-11-09 16:44 UTC (permalink / raw)
  To: Alfred M. Szmidt; +Cc: yuri.v.khan, arthur.miller, emacs-devel

> From: "Alfred M. Szmidt" <ams@gnu.org>
> Cc: arthur.miller@live.com, emacs-devel@gnu.org
> Date: Sat, 09 Nov 2024 11:33:45 -0500
> 
>        (while-let ((run (some-condition)))
> 	 (message "running"))
> 
>    Do you expect that to evaluate (some-condition) once, then, if it’s
>    initially true, run forever?
> 
> That is how it is described in the manual, so yes (some-condition)
> should only be done once, and not every iteration.  See (elisp)
> Conditionals .

Which could mean that the manual is wrong and needs to be fixed.

>       It can be convenient to bind variables in conjunction with using a
>    conditional.  It's often the case that you compute a value, and then
>    want to do something with that value if it's non-‘nil’.  The
>    straightforward way to do that is to just write, for instance:
>    
>         (let ((result1 (do-computation)))
>           (when result1
>             (let ((result2 (do-more result1)))
>               (when result2
>                 (do-something result2)))))
> 
>       Since this is a very common pattern, Emacs provides a number of
>    macros to make this easier and more readable.  The above can be written
>    the following way instead:
> 
> ... following the various with various FOO-let forms, ending with
> while-let.

The above description actually supports what Yuri was saying, not what
Arthur and you expect.



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 16:44                 ` Eli Zaretskii
@ 2024-11-09 16:53                   ` Eli Zaretskii
  2024-11-09 17:33                   ` Andreas Schwab
  2024-11-14 21:50                   ` John ff
  2 siblings, 0 replies; 34+ messages in thread
From: Eli Zaretskii @ 2024-11-09 16:53 UTC (permalink / raw)
  To: ams; +Cc: yuri.v.khan, arthur.miller, emacs-devel

> Date: Sat, 09 Nov 2024 18:44:28 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: yuri.v.khan@gmail.com, arthur.miller@live.com, emacs-devel@gnu.org
> 
> > From: "Alfred M. Szmidt" <ams@gnu.org>
> > Cc: arthur.miller@live.com, emacs-devel@gnu.org
> > Date: Sat, 09 Nov 2024 11:33:45 -0500
> > 
> >        (while-let ((run (some-condition)))
> > 	 (message "running"))
> > 
> >    Do you expect that to evaluate (some-condition) once, then, if it’s
> >    initially true, run forever?
> > 
> > That is how it is described in the manual, so yes (some-condition)
> > should only be done once, and not every iteration.  See (elisp)
> > Conditionals .
> 
> Which could mean that the manual is wrong and needs to be fixed.

The manual might be not explicit enough about this aspect, but it does
say "repeat until a binding in SPEC is ‘nil’", which at least hints
that SPEC is re-evaluated on each iteration.  Because otherwise
repeatedly testing the same result and hoping it will become nil would
be tantamount to the proverbial definition of insanity.



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 16:44                 ` Eli Zaretskii
  2024-11-09 16:53                   ` Eli Zaretskii
@ 2024-11-09 17:33                   ` Andreas Schwab
  2024-11-14 21:50                   ` John ff
  2 siblings, 0 replies; 34+ messages in thread
From: Andreas Schwab @ 2024-11-09 17:33 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Alfred M. Szmidt, yuri.v.khan, arthur.miller, emacs-devel

On Nov 09 2024, Eli Zaretskii wrote:

>>       It can be convenient to bind variables in conjunction with using a
>>    conditional.  It's often the case that you compute a value, and then
>>    want to do something with that value if it's non-‘nil’.  The
>>    straightforward way to do that is to just write, for instance:
>>    
>>         (let ((result1 (do-computation)))
>>           (when result1
>>             (let ((result2 (do-more result1)))
>>               (when result2
>>                 (do-something result2)))))
>> 
>>       Since this is a very common pattern, Emacs provides a number of
>>    macros to make this easier and more readable.  The above can be written
>>    the following way instead:
>> 
>> ... following the various with various FOO-let forms, ending with
>> while-let.
>
> The above description actually supports what Yuri was saying, not what
> Arthur and you expect.

The description only talks about when, where the condition is only
evaluated once not matter what.  If you replace when with while you have
a very different situation.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 21:47             ` Sv: " Joost Kremers
@ 2024-11-10  6:07               ` Andreas Schwab
  0 siblings, 0 replies; 34+ messages in thread
From: Andreas Schwab @ 2024-11-10  6:07 UTC (permalink / raw)
  To: Joost Kremers; +Cc: arthur miller, Yuri Khan, emacs-devel@gnu.org

On Nov 09 2024, Joost Kremers wrote:

> Yes, but for `while`, the pattern isn't complete. The `setq` inside the
> loop is a crucial part:
>
> ```
> (let ((a (foo ...)))
>   (while a
>     (do-stuff-with a)
>     (setq a (foo ...))))
> ```

You can write it like this to avoid typing the condition twice:

 (let (a)
   (while (setq a (foo ...))
     (do-stuff-with a)))

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 20:29                 ` Sv: " arthur miller
@ 2024-11-10  6:22                   ` Eli Zaretskii
  2024-11-10 10:40                     ` Joost Kremers
                                       ` (2 more replies)
  0 siblings, 3 replies; 34+ messages in thread
From: Eli Zaretskii @ 2024-11-10  6:22 UTC (permalink / raw)
  To: arthur miller; +Cc: ams, yuri.v.khan, emacs-devel

> From: arthur miller <arthur.miller@live.com>
> CC: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
> Date: Sat, 9 Nov 2024 20:29:29 +0000
> 
> In other words, there might be variables live outisde of
> the loop-scope we wish to access in the loop, and that is
> what Yuri's example shows. However, i,j are not re-initiated
> on each iteration, but remembers their value. The effecto of
> while-let in current implementation is that i,j are re-initiated
> in each iteration, not re-evaluated, if that makes it clear.
> 
> I am not sure how to illustrate in a better way. The net effect is
> that lexical variables declared in while-let loop are "read-only".
> 
> They are not, but since they are re-iniated, it is pointless to
> write to them.

You can write to them indirectly, if the evaluation is properly
written.  If the evaluation is just assigning a fixed value to a
variable, then yes, writing to that variable in the body is pointless;
but then so is the use of while-let, IMO.

Even in your for-loop example from C, the CONDITION part of the loop
is re-evaluated on each iteration, and if you assign some fixed value
to the loop control variables there, your loop might become an
infloop, regardless of what you do in the body with those variables.
That's basically what the example of while-let you show at the
beginning of this discussion did.

> Of course, all loop predicates should be evaled on each iteration,
> but not re-iniated on each iteration. If that makes sense. Sorry,
> I am not very good at writing.

If while-let doesn't seem to do the job in some code of yours, then
don't use it there.  Use something else.  AFAIU, while-let was
introduced for those cases where its use makes sense and does the job
cleaner and clearer than the alternatives.  It could be abused, of
course, but that's not necessarily its fault, is it?

Anyway, to get this long discussion back on track: is there a need to
clarify something in the documentation of while-let? if so, what?



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-10  6:22                   ` Eli Zaretskii
@ 2024-11-10 10:40                     ` Joost Kremers
  2024-11-10 12:10                       ` Alfred M. Szmidt
  2024-11-10 18:18                     ` Sv: " arthur miller
  2024-11-11 22:41                     ` Joost Kremers
  2 siblings, 1 reply; 34+ messages in thread
From: Joost Kremers @ 2024-11-10 10:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: arthur miller, ams, yuri.v.khan, emacs-devel

On Sun, Nov 10 2024, Eli Zaretskii wrote:
> Anyway, to get this long discussion back on track: is there a need to
> clarify something in the documentation of while-let? if so, what?

Speaking for me personally, I do think the documentation esp. of
`while-let` is too terse. I think two improvements could be made. The first
would be to explicitly mention the pattern that `while-let` replaces, i.e.,

```
(let ((result (do-computation)))
  (while result
    (do-stuff-with result)
    (setq result (do-computation))))
```

The manual at (info "(elisp) Conditionals") discusses the pattern that
`when-let` replaces; `if-let` can be deduced from that, as it's similar.
But `while-let` is different because of the additional `setq` in the
pattern it replaces.

Second, I think it would help if the fact that the bindings are
reestablished upon every iteration were mentioned explicitly. This seems to
have confused Arthur, and I asked myself the same question when I first
encountered `while-let`.

I'd offer the following as a first attempt:

```
@defmac while-let spec then-forms...
Like @code{when-let*}, but repeat until a binding in @var{spec} is
@code{nil}.  The return value is always @code{nil}.

@code{while-let} replaces a common pattern in which a binding is
established outside the @{while}-loop, tested as part of the condition of
@{while} and subsequently changed inside the loop using the same expression
that it was originally bound to:

@example
(let ((result (do-computation)))
  (while result
    (do-stuff-with result)
    (setq result (do-computation))))
@end example

Using @code{while-let}, this can be written more succinctly as:

@example
(while-let ((result (do-computation)))
  (do-stuff-with result))
@end example

The binding of @code{result} is reestablished at every iteration, therefore
setting the value of @code{result} inside the loop has no effect. In order
to end the loop, @code{(do-computation)} should eventually return
@code{nil}.

This example uses a single binding for clarity, but obviously
@code{while-let} can establish multiple bindings. The loop runs as long as
all bindings are non-@code{nil}.
@end defmac
```

Am I mistaken or is `while-let` a bit like a do..until loop that some
languages offer?


-- 
Joost Kremers
Life has its moments



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-10 10:40                     ` Joost Kremers
@ 2024-11-10 12:10                       ` Alfred M. Szmidt
  0 siblings, 0 replies; 34+ messages in thread
From: Alfred M. Szmidt @ 2024-11-10 12:10 UTC (permalink / raw)
  To: Joost Kremers; +Cc: eliz, arthur.miller, yuri.v.khan, emacs-devel

   @defmac while-let spec then-forms...
   Like @code{when-let*}, but repeat until a binding in @var{spec} is
   @code{nil}.  The return value is always @code{nil}.

The "Like FOO" is confusing -- it is not like when-let*, when-let* is
also not like let*.  E.g., when spec is (binding value) or just
(value) (!?) -- which should be mentioned in the manual.

These foo-LET are are mixing up the condition being tested and the
binding, when there is no binding the form seems to be just a test as
if you'd pass it directly to WHEN (or whatever).  There should be some
example that SPEC is not at all like in LET, and that:

(when-let* ((result1 (do-computation))
            (        (do-more result1)))
  (do-something result1))

is something like (I guess?):

(let ((result1 (do-computation)))
  (when result1
    (when (do-more result1)
      (do-something result2))))

And these mentions of "Like LET*" should be removed entierly.

But this is a better, and a good start.

   @code{while-let} replaces a common pattern in which a binding is
   established outside the @{while}-loop, tested as part of the condition of
   @{while} and subsequently changed inside the loop using the same expression
   that it was originally bound to:

   @example
   (let ((result (do-computation)))
     (while result
       (do-stuff-with result)
       (setq result (do-computation))))
   @end example

   Using @code{while-let}, this can be written more succinctly as:

   @example
   (while-let ((result (do-computation)))
     (do-stuff-with result))
   @end example

   The binding of @code{result} is reestablished at every iteration, therefore
   setting the value of @code{result} inside the loop has no effect. In order
   to end the loop, @code{(do-computation)} should eventually return
   @code{nil}.

   This example uses a single binding for clarity, but obviously
   @code{while-let} can establish multiple bindings. The loop runs as long as
   all bindings are non-@code{nil}.
   @end defmac
   ```

   Am I mistaken or is `while-let` a bit like a do..until loop that some
   languages offer?


   -- 
   Joost Kremers
   Life has its moments





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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-10 18:18                     ` Sv: " arthur miller
@ 2024-11-11  5:13                       ` Yuri Khan
  0 siblings, 0 replies; 34+ messages in thread
From: Yuri Khan @ 2024-11-11  5:13 UTC (permalink / raw)
  To: arthur miller; +Cc: Eli Zaretskii, ams@gnu.org, emacs-devel@gnu.org

On Mon, 11 Nov 2024 at 01:18, arthur miller <arthur.miller@live.com> wrote:

> As I understand it now, Emacs while-loop is a unique kind of loop, at least
> I have never seen a construction with such semantic before. The semantic
> of while-let in Emacs is that of for-loop or while-loop in C++, but where
> initialization of loop variables happens on each iteration
>
>     for (int i=0; i<some_bound(); i++) {
>         we can read i here, but
>         we can't write to it
>     }

Comprarison with a for loop is somewhat strained here. The while-let
loop in Elisp is directly analogous to this C++ while loop:

    #include <iostream>

    int main() {
        while (bool run = true) {
            std::cout << "running\n";
            run = false;
        }
        std::cout << "out of loop\n";
    }

and yes, it’s an infloop, too.

What you’re looking for, though, seems to be a while loop with a
break, which is expressed as a catch/throw in Elisp.



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-10  6:22                   ` Eli Zaretskii
  2024-11-10 10:40                     ` Joost Kremers
  2024-11-10 18:18                     ` Sv: " arthur miller
@ 2024-11-11 22:41                     ` Joost Kremers
  2024-11-12 12:19                       ` Eli Zaretskii
  2 siblings, 1 reply; 34+ messages in thread
From: Joost Kremers @ 2024-11-11 22:41 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: arthur miller, ams, yuri.v.khan, emacs-devel

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

On Sun, Nov 10 2024, Eli Zaretskii wrote:
> Anyway, to get this long discussion back on track: is there a need to
> clarify something in the documentation of while-let? if so, what?

Patch attached. Hope it's not too long, while still covering the gist of
what was discussed in this thread.

HTH

-- 
Joost Kremers
Life has its moments


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Improve-documentation-for-while-let.patch --]
[-- Type: text/x-patch, Size: 3621 bytes --]

From fb3fd3bef67de821c469c0edb5b1cd6680736565 Mon Sep 17 00:00:00 2001
From: Joost Kremers <joostkremers@fastmail.com>
Date: Mon, 11 Nov 2024 23:38:49 +0100
Subject: [PATCH] Improve documentation for `while-let'.

* doc/lispref/control.texi: Improve documentation for `while-let`.
---
 doc/lispref/control.texi | 51 +++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 8 deletions(-)

diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 80ed2ce899b..efc57fe7323 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -321,33 +321,68 @@ Conditionals
 There's a number of variations on this theme, and they're briefly
 described below.
 
-@defmac if-let* varlist then-form else-forms...
-Evaluate each binding in @var{varlist} in turn, like in @code{let*}
+@defmac if-let* spec then-form else-forms...
+Evaluate each binding in @var{spec} in turn, like in @code{let*}
 (@pxref{Local Variables}), stopping if a binding value is @code{nil}.
 If all are non-@code{nil}, return the value of @var{then-form},
 otherwise the last form in @var{else-forms}.
 @end defmac
 
-@defmac when-let* varlist then-forms...
+@defmac when-let* spec then-forms...
 Like @code{if-let*}, but without @var{else-forms}.
 @end defmac
 
-@defmac and-let* varlist then-forms...
+@defmac and-let* spec then-forms...
 Like @code{when-let*}, but in addition, if there are no
 @var{then-forms} and all the bindings evaluate to non-@code{nil}, return
 the value of the last binding.
 @end defmac
 
-@defmac while-let spec then-forms...
-Like @code{when-let*}, but repeat until a binding in @var{spec} is
-@code{nil}.  The return value is always @code{nil}.
-@end defmac
+Each element of the @code{spec} argument in these macros has the form
+@code{(@var{symbol} @var{value-form})}: @var{value-form} is evaluated
+and @var{symbol} is locally bound to the result.  As a special case,
+@var{symbol} can be omitted if the result of @var{value-form} just needs
+to be tested and there's no need to bind it to a variable.
 
 Some Lisp programmers follow the convention that @code{and} and
 @code{and-let*} are for forms evaluated for return value, and
 @code{when} and @code{when-let*} are for forms evaluated for side-effect
 with returned values ignored.
 
+A similar macro exists to run a loop until one binding evaluates to
+@code{nil}:
+
+@defmac while-let spec then-forms...
+Evaluate each binding in @var{spec} in turn, stopping if a binding value
+is @code{nil}.  If all are non-@code{nil}, execute @var{then-forms},
+then repeat the loop.  The return value is always @code{nil}.
+
+@code{while-let} replaces a pattern in which a binding is established
+outside the @code{while}-loop, tested as part of the condition of
+@code{while} and subsequently changed inside the loop using the same
+expression that it was originally bound to:
+
+@example
+(let ((result (do-computation)))
+  (while result
+    (do-stuff-with result)
+    (setq result (do-computation))))
+@end example
+
+Using @code{while-let}, this can be written more succinctly as:
+
+@example
+(while-let ((result (do-computation)))
+  (do-stuff-with result))
+@end example
+
+One crucial difference here is the fact that in the first code example,
+@code{result} is scoped outside the @code{wile} loop, whereas in the
+second example, its scope is confined to the @code{while-let} loop.  As
+a result, changing the value of @code{result} inside the loop has no
+effect on the subsequent iteration.
+@end defmac
+
 @node Combining Conditions
 @section Constructs for Combining Conditions
 @cindex combining conditions
-- 
2.47.0


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

* Re: Is this a bug in while-let or do I missunderstand it?
@ 2024-11-12  3:36 arthur miller
  2024-11-12  8:30 ` Joost Kremers
  0 siblings, 1 reply; 34+ messages in thread
From: arthur miller @ 2024-11-12  3:36 UTC (permalink / raw)
  To: joostkremers@fastmail.fm; +Cc: emacs-devel@gnu.org

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

>+@code{while-let} replaces a pattern in which a binding is established
>+outside the @code{while}-loop, tested as part of the condition of
>+@code{while} and subsequently changed inside the loop using the same
>+expression that it was originally bound to:
>+
>+@example
>+(let ((result (do-computation)))
>+  (while result
>+    (do-stuff-with result)
>+    (setq result (do-computation))))
>+@end example
>+
>+Using @code{while-let}, this can be written more succinctly as:
>+
>+@example
>+(while-let ((result (do-computation)))
>+  (do-stuff-with result))
>+@end example
>+
>+One crucial difference here is the fact that in the first code example,
>+@code{result} is scoped outside the @code{wile} loop, whereas in the
>+second example, its scope is confined to the @code{while-let} loop.  As
>+a result, changing the value of @code{result} inside the loop has no
>+effect on the subsequent iteration.
>+@end defmac

The scope of the let-binding is the same in both. The crucial
difference is that in the first example, the user have control over
when and how 'result' is evaluated. The user can for example do:

(let ((result (do-computation)))
  (while result
    (do-stuff-with result)
    (setq result (do-some-other-computation))))

Whereas in the other example, the code is automatically generated
to pass in the original condition calculation, and the user can not
interfere with the computation of the condition.

[-- Attachment #2: Type: text/html, Size: 5976 bytes --]

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

* Re: Is this a bug in while-let or do I missunderstand it?
@ 2024-11-12  3:41 arthur miller
  0 siblings, 0 replies; 34+ messages in thread
From: arthur miller @ 2024-11-12  3:41 UTC (permalink / raw)
  To: joostkremers@fastmail.fm; +Cc: emacs-devel@gnu.org

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

I forgott to say: I am not so very literary inclined, so I don't know how to
catch that in a nice phrase.

[-- Attachment #2: Type: text/html, Size: 587 bytes --]

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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-12  3:36 arthur miller
@ 2024-11-12  8:30 ` Joost Kremers
  2024-11-12 17:55   ` Alfred M. Szmidt
  0 siblings, 1 reply; 34+ messages in thread
From: Joost Kremers @ 2024-11-12  8:30 UTC (permalink / raw)
  To: arthur miller; +Cc: emacs-devel@gnu.org

On Tue, Nov 12 2024, arthur miller wrote:
> The scope of the let-binding is the same in both.

I don't see how. With `while`, `result` is let-bound outside the loop, with
`while-let` it's bound inside the loop, even after macroexpanding it:

```
(macroexpand-all '(while-let ((result (foo)))
                    (bar result)))

==> 

(catch 'done15
  (while t
    (let*
        ((result
          (and t
               (foo))))
      (if result
          (progn
            (bar result))
        (throw 'done15 nil)))))
```

In fact, with `while`, you can use `result` even before you enter the loop:

```

(let ((result (do-something)))
  (do-something-with result)
  ...
  (while result
    (do-something-else-with result)
    (setq result (do-yet-another-thing))))
```

So clearly the scope of `result` is wider.

> The crucial
> difference is that in the first example, the user have control over
> when and how 'result' is evaluated. The user can for example do:
>
> (let ((result (do-computation)))
>   (while result
>     (do-stuff-with result)
>     (setq result (do-some-other-computation))))

Yes, and if that's what you need, you should use `while`.

> Whereas in the other example, the code is automatically generated
> to pass in the original condition calculation, and the user can not
> interfere with the computation of the condition.

Yes, but that's exactly the point of `while-let`. `while-let` is not there
to replace `while`, it's a different macro for a different (though related)
purpose.

Mind you, what you want to do can still be done with `while-let`, provided
you establish the relevant binding *outside* the loop:

```
(let ((continue t))
  (while-let ((a (foo))
              (b (bar))
              (  continue))
    (do-some-stuff)
    ...
    (when (stop-condition)
      (setq continue nil))))
```

I think I understand where your confusion is coming from, and I've tried to
address it in my proposed patch for the documentation. If you feel it's
still not clear enough, I'll happily take another look.

-- 
Joost Kremers
Life has its moments



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-11 22:41                     ` Joost Kremers
@ 2024-11-12 12:19                       ` Eli Zaretskii
  2024-11-12 12:45                         ` Joost Kremers
  2024-11-12 23:45                         ` Joost Kremers
  0 siblings, 2 replies; 34+ messages in thread
From: Eli Zaretskii @ 2024-11-12 12:19 UTC (permalink / raw)
  To: Joost Kremers; +Cc: arthur.miller, ams, yuri.v.khan, emacs-devel

> From: Joost Kremers <joostkremers@fastmail.fm>
> Cc: arthur miller <arthur.miller@live.com>,  ams@gnu.org,
>   yuri.v.khan@gmail.com,  emacs-devel@gnu.org
> Date: Mon, 11 Nov 2024 23:41:50 +0100
> 
> Patch attached. Hope it's not too long, while still covering the gist of
> what was discussed in this thread.

Thanks, see some comments below.

> >From fb3fd3bef67de821c469c0edb5b1cd6680736565 Mon Sep 17 00:00:00 2001
> From: Joost Kremers <joostkremers@fastmail.com>
> Date: Mon, 11 Nov 2024 23:38:49 +0100
> Subject: [PATCH] Improve documentation for `while-let'.
> 
> * doc/lispref/control.texi: Improve documentation for `while-let`.

A nit: this should cite the name of the @node in which the changes
were made (in parens, as if it were a function).

> -@defmac if-let* varlist then-form else-forms...
> -Evaluate each binding in @var{varlist} in turn, like in @code{let*}
> +@defmac if-let* spec then-form else-forms...
> +Evaluate each binding in @var{spec} in turn, like in @code{let*}
>  (@pxref{Local Variables}), stopping if a binding value is @code{nil}.
>  If all are non-@code{nil}, return the value of @var{then-form},
>  otherwise the last form in @var{else-forms}.
>  @end defmac
>  
> -@defmac when-let* varlist then-forms...
> +@defmac when-let* spec then-forms...
>  Like @code{if-let*}, but without @var{else-forms}.
>  @end defmac
>  
> -@defmac and-let* varlist then-forms...
> +@defmac and-let* spec then-forms...
>  Like @code{when-let*}, but in addition, if there are no
>  @var{then-forms} and all the bindings evaluate to non-@code{nil}, return
>  the value of the last binding.
>  @end defmac

One "Like 'when-let*' is borderline-okay; 2 are too many.  Please
describe and-let* either completely stand-alone, without relying on
any prior macro, or as "like 'if-let*'" (since it is almost exactly
like if-let*).

> +Each element of the @code{spec} argument in these macros has the form
> +@code{(@var{symbol} @var{value-form})}: @var{value-form} is evaluated
> +and @var{symbol} is locally bound to the result.  As a special case,
> +@var{symbol} can be omitted if the result of @var{value-form} just needs
> +to be tested and there's no need to bind it to a variable.

This paragraph should be before the macros, not after them.

And the last sentence could use some simplification: it's quite a
mouthful, IMO.

> +A similar macro exists to run a loop until one binding evaluates to
> +@code{nil}:
> +
> +@defmac while-let spec then-forms...
> +Evaluate each binding in @var{spec} in turn, stopping if a binding value
> +is @code{nil}.  If all are non-@code{nil}, execute @var{then-forms},
> +then repeat the loop.  The return value is always @code{nil}.

The "repeat the loop" part should say explicitly that SPEC is
re-evaluated on each loop iteration.  AFAIU, this was the part which
confused people.

> +@code{while-let} replaces a pattern in which a binding is established
> +outside the @code{while}-loop, tested as part of the condition of
> +@code{while} and subsequently changed inside the loop using the same
> +expression that it was originally bound to:
> +
> +@example
> +(let ((result (do-computation)))
> +  (while result
> +    (do-stuff-with result)
> +    (setq result (do-computation))))
> +@end example
> +
> +Using @code{while-let}, this can be written more succinctly as:
> +
> +@example
> +(while-let ((result (do-computation)))
> +  (do-stuff-with result))
> +@end example
> +
> +One crucial difference here is the fact that in the first code example,
> +@code{result} is scoped outside the @code{wile} loop, whereas in the
> +second example, its scope is confined to the @code{while-let} loop.  As
> +a result, changing the value of @code{result} inside the loop has no
> +effect on the subsequent iteration.
> +@end defmac

This is too long a description.  For starters, I don't see the need to
justify the existence of the macro (we don't do that for the others).
The fact that it was the subject of a very long discussion doesn't
mean its documentation must be similarly long ;-)

Can we make this shorter and yet clear enough to improve what we have
there now?



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-12 12:19                       ` Eli Zaretskii
@ 2024-11-12 12:45                         ` Joost Kremers
  2024-11-12 14:34                           ` Eli Zaretskii
  2024-11-12 23:45                         ` Joost Kremers
  1 sibling, 1 reply; 34+ messages in thread
From: Joost Kremers @ 2024-11-12 12:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: arthur.miller, ams, yuri.v.khan, emacs-devel

Hi Eli,

Thanks for your comments. I'll take them into account and come up with a
second version.

One question though:

On Tue, Nov 12 2024, Eli Zaretskii wrote:
[...]
> This is too long a description.

I can cut it down, but:

>  For starters, I don't see the need to
> justify the existence of the macro (we don't do that for the others).

Currently, before the description of `if-let*`, the manual contains an
explanation of the reason why `if-let*` and friends exist:

```
It can be convenient to bind variables in conjunction with using a
conditional.  It's often the case that you compute a value, and then
want to do something with that value if it's non-@code{nil}.  The
straightforward way to do that is to just write, for instance:

@example
(let ((result1 (do-computation)))
  (when result1
    (let ((result2 (do-more result1)))
      (when result2
        (do-something result2)))))
@end example

Since this is a very common pattern, Emacs provides a number of macros
to make this easier and more readable.  The above can be written the
following way instead:

@example
(when-let* ((result1 (do-computation))
            (result2 (do-more result1)))
  (do-something result2))
@end example

There's a number of variations on this theme, and they're briefly
described below.
```

Since `while-let` is a bit more complex, I thought I'd add a similar
explanation for it. I can try and shorten it, but I gather you think it
should be removed altogether?

> Can we make this shorter and yet clear enough to improve what we have
> there now?

I'll do my best. :-)

-- 
Joost Kremers
Life has its moments



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-12 12:45                         ` Joost Kremers
@ 2024-11-12 14:34                           ` Eli Zaretskii
  2024-11-12 15:32                             ` Joost Kremers
  0 siblings, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2024-11-12 14:34 UTC (permalink / raw)
  To: Joost Kremers; +Cc: arthur.miller, ams, yuri.v.khan, emacs-devel

> From: Joost Kremers <joostkremers@fastmail.fm>
> Cc: arthur.miller@live.com,  ams@gnu.org,  yuri.v.khan@gmail.com,
>   emacs-devel@gnu.org
> Date: Tue, 12 Nov 2024 13:45:50 +0100
> 
> >  For starters, I don't see the need to
> > justify the existence of the macro (we don't do that for the others).
> 
> Currently, before the description of `if-let*`, the manual contains an
> explanation of the reason why `if-let*` and friends exist:
> 
> ```
> It can be convenient to bind variables in conjunction with using a
> conditional.  It's often the case that you compute a value, and then
> want to do something with that value if it's non-@code{nil}.  The
> straightforward way to do that is to just write, for instance:
> 
> @example
> (let ((result1 (do-computation)))
>   (when result1
>     (let ((result2 (do-more result1)))
>       (when result2
>         (do-something result2)))))
> @end example
> 
> Since this is a very common pattern, Emacs provides a number of macros
> to make this easier and more readable.  The above can be written the
> following way instead:
> 
> @example
> (when-let* ((result1 (do-computation))
>             (result2 (do-more result1)))
>   (do-something result2))
> @end example
> 
> There's a number of variations on this theme, and they're briefly
> described below.
> ```
> 
> Since `while-let` is a bit more complex, I thought I'd add a similar
> explanation for it. I can try and shorten it, but I gather you think it
> should be removed altogether?

Doesn't the part you quoted cover while-let* as well?



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-12 14:34                           ` Eli Zaretskii
@ 2024-11-12 15:32                             ` Joost Kremers
  0 siblings, 0 replies; 34+ messages in thread
From: Joost Kremers @ 2024-11-12 15:32 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: arthur.miller, ams, yuri.v.khan, emacs-devel

On Tue, Nov 12 2024, Eli Zaretskii wrote:
>> Since `while-let` is a bit more complex, I thought I'd add a similar
>> explanation for it. I can try and shorten it, but I gather you think it
>> should be removed altogether?
>
> Doesn't the part you quoted cover while-let* as well?

To a degree, but `while-let*` has some peculiarities that aren't covered.

Let me come up with a revised version and see what you think.

-- 
Joost Kremers
Life has its moments



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-12  8:30 ` Joost Kremers
@ 2024-11-12 17:55   ` Alfred M. Szmidt
  0 siblings, 0 replies; 34+ messages in thread
From: Alfred M. Szmidt @ 2024-11-12 17:55 UTC (permalink / raw)
  To: Joost Kremers; +Cc: arthur.miller, emacs-devel

   > The scope of the let-binding is the same in both.

   I don't see how. With `while`, `result` is let-bound outside the loop, with
   `while-let` it's bound inside the loop, even after macroexpanding it:

And that is (again) the crux of the matter, one group thinks it is LET
bound outside of the loop, another inside.

Consider this, which will pass nil to BAR, but also reassign RESULT to
whatever FOO returns each iteration; which is the part that is
confusing for those who consider LET to be the binding and scope of
the variables (this also makes it much harder to debug code I think).

(while-let ((result (foo)))
  (setq result nil)
  (bar result))

Which expands to:
 
(catch 'done18
  (while t
    (let* ((result (and t (foo))))
      (if result
	  (progn
	    (setq result nil)
	    (bar result))
	(throw 'done18 nil)))))



   Mind you, what you want to do can still be done with `while-let`, provided
   you establish the relevant binding *outside* the loop:

Then what point is while-let?  Should there be a let-while? And a
let-while-let?  There are 20 occurences of while-let in Emacs ...



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-12 12:19                       ` Eli Zaretskii
  2024-11-12 12:45                         ` Joost Kremers
@ 2024-11-12 23:45                         ` Joost Kremers
  2024-11-13  9:45                           ` Sean Whitton
  1 sibling, 1 reply; 34+ messages in thread
From: Joost Kremers @ 2024-11-12 23:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: arthur.miller, ams, yuri.v.khan, emacs-devel

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

On Tue, Nov 12 2024, Eli Zaretskii wrote:
> Thanks, see some comments below.

Second proposal attached.

I've accounted for all of your comments. Some replies below:

>> >From fb3fd3bef67de821c469c0edb5b1cd6680736565 Mon Sep 17 00:00:00 2001
> One "Like 'when-let*' is borderline-okay; 2 are too many.  Please
> describe and-let* either completely stand-alone, without relying on
> any prior macro, or as "like 'if-let*'" (since it is almost exactly
> like if-let*).

I didn't write that, that was the documentation until now. :-) In the new
patch, I replaced these "Like 'when-let*'" with proper descriptions (worded
identically to the extent possible).

>> +Each element of the @code{spec} argument in these macros has the form
>> +@code{(@var{symbol} @var{value-form})}: @var{value-form} is evaluated
>> +and @var{symbol} is locally bound to the result.  As a special case,
>> +@var{symbol} can be omitted if the result of @var{value-form} just needs
>> +to be tested and there's no need to bind it to a variable.
>
> This paragraph should be before the macros, not after them.

I ended up putting it in the description of the first macro (`if-let*`) and
referring to it in the others, because the relevant variable (here SPEC) is
actually called VARLIST in `if-let*`, `when-let*` and `and-let*`, but SPEC
in while-let. (The non-starred versions also have SPEC, but they're being
deprecated. BTW, any reason why `while-let` isn't called `while-let*`?)

>> +@code{while-let} replaces a pattern in which a binding is established
>> +outside the @code{while}-loop, tested as part of the condition of
>> +@code{while} and subsequently changed inside the loop using the same
>> +expression that it was originally bound to:
>> +
>> +@example
>> +(let ((result (do-computation)))
>> +  (while result
>> +    (do-stuff-with result)
>> +    (setq result (do-computation))))
>> +@end example
>> +
>> +Using @code{while-let}, this can be written more succinctly as:
>> +
>> +@example
>> +(while-let ((result (do-computation)))
>> +  (do-stuff-with result))
>> +@end example
>> +
>> +One crucial difference here is the fact that in the first code example,
>> +@code{result} is scoped outside the @code{wile} loop, whereas in the
>> +second example, its scope is confined to the @code{while-let} loop.  As
>> +a result, changing the value of @code{result} inside the loop has no
>> +effect on the subsequent iteration.
>> +@end defmac
>
> This is too long a description.

I've taken it out completely, and put the most important points in the
description of `while-let` directly. Turns out, comparing `while-let` to
`while` may even be confusing, because the relevant bindings have different
scopes in the two snippets.

-- 
Joost Kremers
Life has its moments


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Improve-documentation-for-while-let.patch --]
[-- Type: text/x-patch, Size: 3718 bytes --]

From f426c242411b4538e913da31dac7b6b204c288e8 Mon Sep 17 00:00:00 2001
From: Joost Kremers <joostkremers@fastmail.com>
Date: Mon, 11 Nov 2024 23:38:49 +0100
Subject: [PATCH] Improve documentation for `while-let'.

* doc/lispref/control.texi: Improve documentation for `while-let`.
---
 doc/lispref/control.texi | 52 +++++++++++++++++++++++++++++-----------
 1 file changed, 38 insertions(+), 14 deletions(-)

diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 80ed2ce899b..40e23bc2453 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -322,32 +322,56 @@ Conditionals
 described below.
 
 @defmac if-let* varlist then-form else-forms...
-Evaluate each binding in @var{varlist} in turn, like in @code{let*}
-(@pxref{Local Variables}), stopping if a binding value is @code{nil}.
-If all are non-@code{nil}, return the value of @var{then-form},
-otherwise the last form in @var{else-forms}.
+Evaluate each binding in @var{varlist}, stopping if a binding value is
+@code{nil}.  If all are non-@code{nil}, return the value of
+@var{then-form}, otherwise the last form in @var{else-forms}.
+
+Each element of @code{varlist} has the form @code{(@var{symbol}
+@var{value-form})}: @var{value-form} is evaluated and @var{symbol} is
+locally bound to the result.  Bindings are sequential, as in @code{let*}
+(@pxref{Local Variables}).  As a special case, @var{symbol} can be
+omitted if only the test result of @var{value-form} is of interest:
+@var{value-form} is evaluated and checked for @code{nil}, but its value
+is not bound.
 @end defmac
 
 @defmac when-let* varlist then-forms...
-Like @code{if-let*}, but without @var{else-forms}.
+Evaluate each binding in @var{varlist}, stopping if a binding value is
+@code{nil}.  If all are non-@code{nil}, return the value of the last
+form in @var{then-forms}.  @var{varlist} has the same form as in
+@code{if-let*}.
 @end defmac
 
 @defmac and-let* varlist then-forms...
-Like @code{when-let*}, but in addition, if there are no
-@var{then-forms} and all the bindings evaluate to non-@code{nil}, return
-the value of the last binding.
-@end defmac
-
-@defmac while-let spec then-forms...
-Like @code{when-let*}, but repeat until a binding in @var{spec} is
-@code{nil}.  The return value is always @code{nil}.
+Evaluate each binding in @var{varlist}, stopping if a binding value is
+@code{nil}.  If all are non-@code{nil}, return the value of the last
+form in @var{then-forms}, or, if there are no @var{then-forms}, return
+the value of the last binding.  @var{varlist} has the same form as in
+@code{if-let*}.
 @end defmac
 
 Some Lisp programmers follow the convention that @code{and} and
-@code{and-let*} are for forms evaluated for return value, and
+@code{and-let*} are for forms evaluated for their return value, and
 @code{when} and @code{when-let*} are for forms evaluated for side-effect
 with returned values ignored.
 
+A similar macro exists to run a loop until one binding evaluates to
+@code{nil}:
+
+@defmac while-let spec then-forms...
+Evaluate each binding in @var{spec} in turn, stopping if a binding value
+is @code{nil}.  If all are non-@code{nil}, execute @var{then-forms},
+then repeat the loop.  Note that when the loop is repeated, the
+@var{value-forms} in @var{spec} are re-evaluated and the bindings are
+established anew.
+
+@var{spec} has the same form as the @var{varlist} argument in
+@code{if-let*}.  This means among other things that its bindings are in
+sequence, as with @code{let*} (@pxref{Local Variables}).
+
+The return value of @code{while-let} is always @code{nil}.
+@end defmac
+
 @node Combining Conditions
 @section Constructs for Combining Conditions
 @cindex combining conditions
-- 
2.47.0


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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-12 23:45                         ` Joost Kremers
@ 2024-11-13  9:45                           ` Sean Whitton
  2024-11-13  9:56                             ` Sean Whitton
  0 siblings, 1 reply; 34+ messages in thread
From: Sean Whitton @ 2024-11-13  9:45 UTC (permalink / raw)
  To: Joost Kremers; +Cc: Eli Zaretskii, arthur.miller, ams, yuri.v.khan, emacs-devel

Hello,

On Wed 13 Nov 2024 at 12:45am +01, Joost Kremers wrote:

> On Tue, Nov 12 2024, Eli Zaretskii wrote:
>> Thanks, see some comments below.
>
> Second proposal attached.

Please put the "like let*" back in (the first change in your patch).
There is one person who dislikes it but I think the average reader of
the Elisp reference will benefit.

> BTW, any reason why `while-let` isn't called `while-let*`?)

Just what it got named when it got added; probably a less-than-ideal
decision, with hindsight.  Unlike the if-let/when-let deprecation, it's
not worth renaming it.

-- 
Sean Whitton



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-13  9:45                           ` Sean Whitton
@ 2024-11-13  9:56                             ` Sean Whitton
  2024-11-13 11:00                               ` Joost Kremers
  2024-11-14 21:51                               ` John ff
  0 siblings, 2 replies; 34+ messages in thread
From: Sean Whitton @ 2024-11-13  9:56 UTC (permalink / raw)
  To: Joost Kremers; +Cc: Eli Zaretskii, arthur.miller, ams, yuri.v.khan, emacs-devel

Hello,

On Wed 13 Nov 2024 at 05:45pm +08, Sean Whitton wrote:

> Please put the "like let*" back in (the first change in your patch).
> There is one person who dislikes it but I think the average reader of
> the Elisp reference will benefit.

Oops -- you just moved it.

I have one further comment on your patch:

>  Some Lisp programmers follow the convention that @code{and} and
> -@code{and-let*} are for forms evaluated for return value, and
> +@code{and-let*} are for forms evaluated for their return value, and
>  @code{when} and @code{when-let*} are for forms evaluated for side-effect
>  with returned values ignored.

This change renders the sentence grammatically incorrect.

It needs to be either

"for return value" and "for side-effect"

or

"for their return values" and "for the side-effects of their evaluation".

I think it's better to use the shorter one (i.e., make no changes here).

-- 
Sean Whitton



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-13  9:56                             ` Sean Whitton
@ 2024-11-13 11:00                               ` Joost Kremers
  2024-11-13 12:17                                 ` Sean Whitton
  2024-11-14  7:55                                 ` Eli Zaretskii
  2024-11-14 21:51                               ` John ff
  1 sibling, 2 replies; 34+ messages in thread
From: Joost Kremers @ 2024-11-13 11:00 UTC (permalink / raw)
  To: Sean Whitton; +Cc: Eli Zaretskii, emacs-devel

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

On Wed, Nov 13 2024, Sean Whitton wrote:
> Hello,

> BTW, any reason why `while-let` isn't called `while-let*`?)

Just what it got named when it got added; probably a less-than-ideal
decision, with hindsight.  Unlike the if-let/when-let deprecation, it's
not worth renaming it.

Well, to me, the fact that `if-let*` c.s. are starred (and
the non-starred versions are deprecated) makes sense because their bindings
function the same way as those of `let*`. Given that, one might think that
the bindings of `while-let` function like those of `let`, which is not the
case. That, to me, would be reason enough to rename it. (Keeping `while-let`
as an alias, I guess.)

> On Wed 13 Nov 2024 at 05:45pm +08, Sean Whitton wrote:
>
>> Please put the "like let*" back in (the first change in your patch).
>> There is one person who dislikes it but I think the average reader of
>> the Elisp reference will benefit.
>
> Oops -- you just moved it.

Yeah, I decided to include it in the description of `if-let*`, not as a
separate paragraph, because someone looking up `if-let*` in the manual
might not actually read the text above the macro's description.

>>  Some Lisp programmers follow the convention that @code{and} and
>> -@code{and-let*} are for forms evaluated for return value, and
>> +@code{and-let*} are for forms evaluated for their return value, and
>>  @code{when} and @code{when-let*} are for forms evaluated for side-effect
>>  with returned values ignored.
>
> This change renders the sentence grammatically incorrect.
>
> It needs to be either
>
> "for return value" and "for side-effect"
>
> or
>
> "for their return values" and "for the side-effects of their evaluation".
>
> I think it's better to use the shorter one (i.e., make no changes here).

OK, updated patch attached.

-- 
Joost Kremers
Life has its moments


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Improve-documentation-for-while-let.patch --]
[-- Type: text/x-patch, Size: 3620 bytes --]

From c5009870df4738a4b1446aef7dc24488c8c956a4 Mon Sep 17 00:00:00 2001
From: Joost Kremers <joostkremers@fastmail.com>
Date: Mon, 11 Nov 2024 23:38:49 +0100
Subject: [PATCH] Improve documentation for `while-let'.

* doc/lispref/control.texi: Improve documentation for `while-let`.
---
 doc/lispref/control.texi | 50 +++++++++++++++++++++++++++++-----------
 1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 80ed2ce899b..94eb4769ae0 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -322,25 +322,32 @@ Conditionals
 described below.
 
 @defmac if-let* varlist then-form else-forms...
-Evaluate each binding in @var{varlist} in turn, like in @code{let*}
-(@pxref{Local Variables}), stopping if a binding value is @code{nil}.
-If all are non-@code{nil}, return the value of @var{then-form},
-otherwise the last form in @var{else-forms}.
+Evaluate each binding in @var{varlist}, stopping if a binding value is
+@code{nil}.  If all are non-@code{nil}, return the value of
+@var{then-form}, otherwise the last form in @var{else-forms}.
+
+Each element of @code{varlist} has the form @code{(@var{symbol}
+@var{value-form})}: @var{value-form} is evaluated and @var{symbol} is
+locally bound to the result.  Bindings are sequential, as in @code{let*}
+(@pxref{Local Variables}).  As a special case, @var{symbol} can be
+omitted if only the test result of @var{value-form} is of interest:
+@var{value-form} is evaluated and checked for @code{nil}, but its value
+is not bound.
 @end defmac
 
 @defmac when-let* varlist then-forms...
-Like @code{if-let*}, but without @var{else-forms}.
+Evaluate each binding in @var{varlist}, stopping if a binding value is
+@code{nil}.  If all are non-@code{nil}, return the value of the last
+form in @var{then-forms}.  @var{varlist} has the same form as in
+@code{if-let*}.
 @end defmac
 
 @defmac and-let* varlist then-forms...
-Like @code{when-let*}, but in addition, if there are no
-@var{then-forms} and all the bindings evaluate to non-@code{nil}, return
-the value of the last binding.
-@end defmac
-
-@defmac while-let spec then-forms...
-Like @code{when-let*}, but repeat until a binding in @var{spec} is
-@code{nil}.  The return value is always @code{nil}.
+Evaluate each binding in @var{varlist}, stopping if a binding value is
+@code{nil}.  If all are non-@code{nil}, return the value of the last
+form in @var{then-forms}, or, if there are no @var{then-forms}, return
+the value of the last binding.  @var{varlist} has the same form as in
+@code{if-let*}.
 @end defmac
 
 Some Lisp programmers follow the convention that @code{and} and
@@ -348,6 +355,23 @@ Conditionals
 @code{when} and @code{when-let*} are for forms evaluated for side-effect
 with returned values ignored.
 
+A similar macro exists to run a loop until one binding evaluates to
+@code{nil}:
+
+@defmac while-let spec then-forms...
+Evaluate each binding in @var{spec} in turn, stopping if a binding value
+is @code{nil}.  If all are non-@code{nil}, execute @var{then-forms},
+then repeat the loop.  Note that when the loop is repeated, the
+@var{value-forms} in @var{spec} are re-evaluated and the bindings are
+established anew.
+
+@var{spec} has the same form as the @var{varlist} argument in
+@code{if-let*}.  This means among other things that its bindings are in
+sequence, as with @code{let*} (@pxref{Local Variables}).
+
+The return value of @code{while-let} is always @code{nil}.
+@end defmac
+
 @node Combining Conditions
 @section Constructs for Combining Conditions
 @cindex combining conditions
-- 
2.47.0


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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-13 11:00                               ` Joost Kremers
@ 2024-11-13 12:17                                 ` Sean Whitton
  2024-11-14  7:55                                 ` Eli Zaretskii
  1 sibling, 0 replies; 34+ messages in thread
From: Sean Whitton @ 2024-11-13 12:17 UTC (permalink / raw)
  To: Joost Kremers; +Cc: Eli Zaretskii, emacs-devel

Hello,

On Wed 13 Nov 2024 at 12:00pm +01, Joost Kremers wrote:

> OK, updated patch attached.

Thanks.  Let's give Eli a chance to look.

-- 
Sean Whitton



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-13 11:00                               ` Joost Kremers
  2024-11-13 12:17                                 ` Sean Whitton
@ 2024-11-14  7:55                                 ` Eli Zaretskii
  2024-11-14  8:21                                   ` Joost Kremers
  1 sibling, 1 reply; 34+ messages in thread
From: Eli Zaretskii @ 2024-11-14  7:55 UTC (permalink / raw)
  To: Joost Kremers; +Cc: spwhitton, emacs-devel

> From: Joost Kremers <joostkremers@fastmail.fm>
> Cc: Eli Zaretskii <eliz@gnu.org>,  emacs-devel@gnu.org
> Date: Wed, 13 Nov 2024 12:00:36 +0100
> 
> >> +Each element of the @code{spec} argument in these macros has the form
> >> +@code{(@var{symbol} @var{value-form})}: @var{value-form} is evaluated
> >> +and @var{symbol} is locally bound to the result.  As a special case,
> >> +@var{symbol} can be omitted if the result of @var{value-form} just needs
> >> +to be tested and there's no need to bind it to a variable.
> >
> > This paragraph should be before the macros, not after them.
> 
> I ended up putting it in the description of the first macro (`if-let*`) and
> referring to it in the others, because the relevant variable (here SPEC) is
> actually called VARLIST in `if-let*`, `when-let*` and `and-let*`, but SPEC
> in while-let. (The non-starred versions also have SPEC, but they're being
> deprecated. BTW, any reason why `while-let` isn't called `while-let*`?)

The disadvantage of what you did is that you need to say repeatedly

  @var{varlist} has the same form as in @code{if-let*}.

and the reader has to go back, read the description of if-let* (which
she might not want to know anything about), and decide which parts of
that description are relevant to whatever macro she is interested in.
I frequently find such practices in a manual annoying, especially when
I need to consult it for some specific detail, and don't have time for
reading other parts which are of no interest to me.

We should always keep in mind that the most important use pattern of
the manual is as a reference, where the reader is interested only in
some very specific subject, so any need to read more than the minimum
is an annoyance to be avoided.

> +Each element of @code{varlist} has the form @code{(@var{symbol}
> +@var{value-form})}:

This form is better put in @w{..}, to prevent it being split between
lines.

Other than those nits, the new text LGTM, thanks.



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-14  7:55                                 ` Eli Zaretskii
@ 2024-11-14  8:21                                   ` Joost Kremers
  0 siblings, 0 replies; 34+ messages in thread
From: Joost Kremers @ 2024-11-14  8:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: spwhitton, emacs-devel

On Thu, Nov 14 2024, Eli Zaretskii wrote:
>> From: Joost Kremers <joostkremers@fastmail.fm>
>> I ended up putting it in the description of the first macro (`if-let*`) and
>> referring to it in the others, because the relevant variable (here SPEC) is
>> actually called VARLIST in `if-let*`, `when-let*` and `and-let*`, but SPEC
>> in while-let. (The non-starred versions also have SPEC, but they're being
>> deprecated. BTW, any reason why `while-let` isn't called `while-let*`?)
>
> The disadvantage of what you did is that you need to say repeatedly
>
>   @var{varlist} has the same form as in @code{if-let*}.
>
> and the reader has to go back, read the description of if-let* (which
> she might not want to know anything about), and decide which parts of
> that description are relevant to whatever macro she is interested in.

Okay, so I'll put the explanation of VARLIST into the description of every
macro.

>> +Each element of @code{varlist} has the form @code{(@var{symbol}
>> +@var{value-form})}:
>
> This form is better put in @w{..}, to prevent it being split between
> lines.

Ok.

-- 
Joost Kremers
Life has its moments



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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-09 16:44                 ` Eli Zaretskii
  2024-11-09 16:53                   ` Eli Zaretskii
  2024-11-09 17:33                   ` Andreas Schwab
@ 2024-11-14 21:50                   ` John ff
  2 siblings, 0 replies; 34+ messages in thread
From: John ff @ 2024-11-14 21:50 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Alfred M. Szmidt, Yuri Khan, arthur.miller, emacs-devel




-------- Original Message --------
From: Eli Zaretskii <eliz@gnu.org>
Sent: Sat Nov 09 16:44:28 GMT 2024
To: "Alfred M. Szmidt" <ams@gnu.org>
Cc: yuri.v.khan@gmail.com, arthur.miller@live.com, emacs-devel@gnu.org
Subject: Re: Is this a bug in while-let or do I missunderstand it?

> From: "Alfred M. Szmidt" <ams@gnu.org>
> Cc: arthur.miller@live.com, emacs-devel@gnu.org
> Date: Sat, 09 Nov 2024 11:33:45 -0500
> 
>        (while-let ((run (some-condition)))
> 	 (message "running"))
> 
>    Do you expect that to evaluate (some-condition) once, then, if it’s
>    initially true, run forever?
> 
> That is how it is described in the manual, so yes (some-condition)
> should only be done once, and not every iteration.  See (elisp)
> Conditionals .

Which could mean that the manual is wrong and needs to be fixed.

>       It can be convenient to bind variables in conjunction with using a
>    conditional.  It's often the case that you compute a value, and then
>    want to do something with that value if it's non-‘nil’.  The
>    straightforward way to do that is to just write, for instance:
>    
>         (let ((result1 (do-computation)))
>           (when result1
>             (let ((result2 (do-more result1)))
>               (when result2
>                 (do-something result2)))))
> 
>       Since this is a very common pattern, Emacs provides a number of
>    macros to make this easier and more readable.  The above can be written
>    the following way instead:
> 
> ... following the various with various FOO-let forms, ending with
> while-let.

The above description actually supports what Yuri was saying, not what
Arthur and you expect.





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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-13  9:56                             ` Sean Whitton
  2024-11-13 11:00                               ` Joost Kremers
@ 2024-11-14 21:51                               ` John ff
  2024-11-14 21:52                                 ` John ff
  1 sibling, 1 reply; 34+ messages in thread
From: John ff @ 2024-11-14 21:51 UTC (permalink / raw)
  To: Sean Whitton
  Cc: Joost Kremers, Eli Zaretskii, arthur.miller, ams, yuri.v.khan,
	emacs-devel




-------- Original Message --------
From: Sean Whitton <spwhitton@spwhitton.name>
Sent: Wed Nov 13 09:56:00 GMT 2024
To: Joost Kremers <joostkremers@fastmail.fm>
Cc: Eli Zaretskii <eliz@gnu.org>, arthur.miller@live.com, ams@gnu.org, yuri.v.khan@gmail.com, emacs-devel@gnu.org
Subject: Re: Is this a bug in while-let or do I missunderstand it?

Hello,

On Wed 13 Nov 2024 at 05:45pm +08, Sean Whitton wrote:

> Please put the "like let*" back in (the first change in your patch).
> There is one person who dislikes it but I think the average reader of
> the Elisp reference will benefit.

Oops -- you just moved it.

I have one further comment on your patch:

>  Some Lisp programmers follow the convention that @code{and} and
> -@code{and-let*} are for forms evaluated for return value, and
> +@code{and-let*} are for forms evaluated for their return value, and
>  @code{when} and @code{when-let*} are for forms evaluated for side-effect
>  with returned values ignored.

This change renders the sentence grammatically incorrect.

It needs to be either

"for return value" and "for side-effect"

or

"for their return values" and "for the side-effects of their evaluation".

I think it's better to use the shorter one (i.e., make no changes here).

-- 
Sean Whitton





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

* Re: Is this a bug in while-let or do I missunderstand it?
  2024-11-14 21:51                               ` John ff
@ 2024-11-14 21:52                                 ` John ff
  0 siblings, 0 replies; 34+ messages in thread
From: John ff @ 2024-11-14 21:52 UTC (permalink / raw)
  To: Sean Whitton
  Cc: Joost Kremers, Eli Zaretskii, arthur.miller, ams, yuri.v.khan,
	emacs-devel




-------- Original Message --------
From: John ff <jpff@codemist.co.uk>
Sent: Thu Nov 14 21:51:11 GMT 2024
To: Sean Whitton <spwhitton@spwhitton.name>
Cc: Joost Kremers <joostkremers@fastmail.fm>, Eli Zaretskii <eliz@gnu.org>, arthur.miller@live.com, ams@gnu.org, yuri.v.khan@gmail.com, emacs-devel@gnu.org
Subject: Re: Is this a bug in while-let or do I missunderstand it?




-------- Original Message --------
From: Sean Whitton <spwhitton@spwhitton.name>
Sent: Wed Nov 13 09:56:00 GMT 2024
To: Joost Kremers <joostkremers@fastmail.fm>
Cc: Eli Zaretskii <eliz@gnu.org>, arthur.miller@live.com, ams@gnu.org, yuri.v.khan@gmail.com, emacs-devel@gnu.org
Subject: Re: Is this a bug in while-let or do I missunderstand it?

Hello,

On Wed 13 Nov 2024 at 05:45pm +08, Sean Whitton wrote:

> Please put the "like let*" back in (the first change in your patch).
> There is one person who dislikes it but I think the average reader of
> the Elisp reference will benefit.

Oops -- you just moved it.

I have one further comment on your patch:

>  Some Lisp programmers follow the convention that @code{and} and
> -@code{and-let*} are for forms evaluated for return value, and
> +@code{and-let*} are for forms evaluated for their return value, and
>  @code{when} and @code{when-let*} are for forms evaluated for side-effect
>  with returned values ignored.

This change renders the sentence grammatically incorrect.

It needs to be either

"for return value" and "for side-effect"

or

"for their return values" and "for the side-effects of their evaluation".

I think it's better to use the shorter one (i.e., make no changes here).

-- 
Sean Whitton





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

end of thread, other threads:[~2024-11-14 21:52 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-12  3:41 Is this a bug in while-let or do I missunderstand it? arthur miller
  -- strict thread matches above, loose matches on Subject: below --
2024-11-12  3:36 arthur miller
2024-11-12  8:30 ` Joost Kremers
2024-11-12 17:55   ` Alfred M. Szmidt
2024-11-08 16:25 arthur miller
2024-11-08 19:23 ` Philip Kaludercic
2024-11-09  9:29 ` Yuri Khan
2024-11-09 13:03   ` Sv: " arthur miller
2024-11-09 13:15     ` Yuri Khan
2024-11-09 13:38       ` Sv: " arthur miller
2024-11-09 13:41         ` Yuri Khan
2024-11-09 13:47           ` Sv: " arthur miller
2024-11-09 14:04             ` Yuri Khan
2024-11-09 16:33               ` Alfred M. Szmidt
2024-11-09 16:44                 ` Eli Zaretskii
2024-11-09 16:53                   ` Eli Zaretskii
2024-11-09 17:33                   ` Andreas Schwab
2024-11-14 21:50                   ` John ff
2024-11-09 20:29                 ` Sv: " arthur miller
2024-11-10  6:22                   ` Eli Zaretskii
2024-11-10 10:40                     ` Joost Kremers
2024-11-10 12:10                       ` Alfred M. Szmidt
2024-11-10 18:18                     ` Sv: " arthur miller
2024-11-11  5:13                       ` Yuri Khan
2024-11-11 22:41                     ` Joost Kremers
2024-11-12 12:19                       ` Eli Zaretskii
2024-11-12 12:45                         ` Joost Kremers
2024-11-12 14:34                           ` Eli Zaretskii
2024-11-12 15:32                             ` Joost Kremers
2024-11-12 23:45                         ` Joost Kremers
2024-11-13  9:45                           ` Sean Whitton
2024-11-13  9:56                             ` Sean Whitton
2024-11-13 11:00                               ` Joost Kremers
2024-11-13 12:17                                 ` Sean Whitton
2024-11-14  7:55                                 ` Eli Zaretskii
2024-11-14  8:21                                   ` Joost Kremers
2024-11-14 21:51                               ` John ff
2024-11-14 21:52                                 ` John ff
2024-11-09 21:47             ` Sv: " Joost Kremers
2024-11-10  6:07               ` Andreas Schwab

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.