>> 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.
That depends how you define the while-let semantics of course.
>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.
Infloops are not in question here, since they are results of a programmers
misstake. The job of for-loop in C or while-let in Emacs is not to ensure
always terminating loop.
>That's basically what the example of while-let you show at the
>beginning of this discussion did.
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
}
Since re-initialization is happening on each iteration, as you say we have
to go via a third variable (or a function), and the variable must not be shadowed
by the local binding established by while-let spec. That does make while-let
pointless to use for not so unusual idiom in other languages:
(let ((run t))
(while run
...
(when (some-condition)
(setf run nil))))
I personally would expect to be able to write:
(while-let ((run t))
...
(when (some-condition)
(setf run nil)))
Since while-let was supposed to simplify that case, but that wont work :).
So obviously I did missunderstood how while-let works, but I would say the
semantics are bit arcane. I haven't seen any other language with read-only
semantic for loop variables.
Somebody said in another mail that bindings are conditions. I think it is a
good illustration of while-let bindings, but it perhaps does not catch the
fact that they are not used as ordinary lexical bindings strongly enough, so,
perhaps a mention about not being settable from the loop is in order?
That would also be my answer for the question in another mail about what
to add to docs. Also perhaps mention that the way out of that loop is to either
go via an implicit variable, or to use try/catch or cl-block/cl-return-from to
break out of the loop.
As a remark:
Perhaps while-let is a wrong name for this construct to start with. It behaves
more like for-loops, but with a twist. Typically in C/C++ and derivatives, we
can't introduce a variable in while condition: while (int i = some_var ) is not
legal.
Since those bindings are not settable in loop body; they really are conditions,
perhaps while* is a better name for this construct, since it introduces
multiple conditions. But it is not good either, since this construct is really
somewhere in-between a while and for loop from other languages.
Från: Eli Zaretskii <eliz@gnu.org>
Skickat: den 10 november 2024 07:22
Till: arthur miller <arthur.miller@live.com>
Kopia: ams@gnu.org <ams@gnu.org>; yuri.v.khan@gmail.com <yuri.v.khan@gmail.com>; emacs-devel@gnu.org <emacs-devel@gnu.org>
Ämne: Re: Is this a bug in while-let or do I missunderstand it?
> 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?