emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Is this a bug in while-let or do I missunderstand it?


From: Eli Zaretskii
Subject: Re: Is this a bug in while-let or do I missunderstand it?
Date: Tue, 12 Nov 2024 14:19:36 +0200

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]