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

Yes.

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

Mnjah; more like this:

(catch 'done
  (while t
    (let* ((run nil))
      (if run
          (do-body)
          (throw 'done nil)))))

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. But the worst, we can see that the
claimed optimizaiton does not take place at all:

(pp (macroexpand-all
     '(while-let ((run t)
                  (x 'expensive)
                  (y 'more-expensive)
                  (z 'the-most-expensive))
        (message "running")
        (setf run nil))))

(catch 'done1522
  (while t
    (let*
        ((run (and t t)) (x (and run 'expensive)) (y (and x 'more-expensive))
         (z (and y 'the-most-expensive)))
      (if z (progn (message "running") (setq run nil)) (throw 'done1522 nil)))))

Which makes wonder if the convoluted code in subr.el is worth compared to the
naive implementation I posted. Perhaps someone can pull off the optimization with
 some clever macro, I don't know. 

I think it was enough from me as an outsider to point out the possible bug. Whether
 people here wants to poop on it, or acknowledge and fix the bug is not up to me. 

In other words, I think I am done here.

/best regards

Från: Yuri Khan <yuri.v.khan@gmail.com>
Skickat: den 9 november 2024 14:15
Till: arthur miller <arthur.miller@live.com>
Kopia: emacs-devel@gnu.org <emacs-devel@gnu.org>
Ämne: Re: Is this a bug in while-let or do I missunderstand it?
 
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
    )