|
From: | Drew Adams |
Subject: | RE: [External] : Re: Is this a bug in while-let or do I missunderstand it? |
Date: | Sat, 9 Nov 2024 22:36:34 +0000 |
Below. From: arthur miller Sent: Saturday, November 9, 2024 11:33 AM >IMHO, this is a problem with all of the >if/and/when/while-let[*] thingies. If someone >uses them a lot then she probably knows what >goes on, in what sequence. But a priori it's >not so clear. Only while-let. The lack of obvious behavior/meaning and clear doc is a problem with them in general, IMO. In particular, it wouldn't hurt to show an example of what each can expand to, in terms of let[*] etc. We do that in the Elisp manual when introducing cond,
for example: For example: (if A B C)
≡ (cond (A B) (t C)) (We could even usefully do it to show let* in terms of let.) >This may just mean that the doc needs to take
pains to be very clear, maybe even with examples
or by showing a macro expansion explicitly. > >Using catch/throw, let[*], and/if/when/while
together is always _clearer_, IMO. And it's
often no more verbose. I don't think so.
(catch/throw aren't needed for some of the *-let constructs, of course.) IMO, use of explicit let, for binding, and explicit if/when/etc. for control flow, is clear. And if you don't use the *-let thingies much, or are new to
them, then the former are clearer. Hence the need for good doc for the *-let combination bind&control constructs, at a minimum. As you say, the *-let constructs are just "shorthand". And not much shorter, typically. Shorthand, but mentally more complex. The complexity isn't visual,
it's in their meanings/behaviors, i.e., mental. I'm not against all combinations of binding constructs with control constructs. E.g., constructs such as dolist bind vars. I just don't see much mileage/clarity
gain from the *-let thingies. YMMV. At a minimum, their doc should be made very clear. (let ((var1 init1)
... (varN initN) (loop-invarant init-loop-invariant)) ... (while loop-invariant
...) ...) In this context you are leaking loop-invariant in the
entire scope of enclosing let-form, whereas (let ((var1 init1)
... (varN initN)) ... (while ((loop-invariant init-loop-invariant)) ...) ...) limits 'loop-invariant' to the lexical environment
of while loop. What's your argument? That there's no need to bind a local var for init-loop-invariant? OK. How's that relevant here? (And there's no *-let construct in either of those examples, so ... what are you really comparing/demonstrating?) In any case, if you did need a local var and wanted to keep its scope within the while you'd just wrap the while with its own let - end of story: (let ((var1 init1) ... (varN initN) ... (let ((loop-invarant init-loop-invariant)) (while loop-invariant ...)) ...) Using a separate let makes clear where you want/need a separate binding scope. ___ It's enough for someone to scan this mail thread, to see possible confusion over what while-let does and how/when/where it does what
à QED. E.g., suggestions such as this, to help clarify the meaning/behavior of a while-let, make clear that
it isn't so clear on its own: >I'd align such clauses like this: > > (while-let (( b) > ( (< b end)) > (e (next-single-property-change > (1+ b) 'erc--msg nil end))) > ...) > >to emphasize that. I'm not saying such intentional formatting wouldn't help; it could. But suggesting such formatting just underlines how unclear the while-let construct seems
to be, a priori. Again, maybe a doc improvement could help. Or a pointer to this thread, where the back-&-forth might unconfuse someone a bit... ;-) Från: Drew Adams
Skickat: den 9 november 2024 19:07 IMHO, this is a problem with all of the |
[Prev in Thread] | Current Thread | [Next in Thread] |