Subject: bug#73853: Should and-let* become a synonym for when-let*?

From: Michael Heerdegen <[email-masked]>
Date: Sun, 19 Jan 2025 02:41:46 +0100

Stefan Monnier <[email-masked]> writes:

> My argument is not that it's a bad convention.  Instead I'm arguing
> that the supposed benefit of this convention doesn't really apply because
> it's not obeyed widely enough.

Lots of conventions are not obeyed widely.  If you (I mean Stefan M.) do
care about them you use to change the occurrences.

One goal when designing the language is that its constructs suggest a
good style.  Sometimes people need to be reminded, as you know, think of
quoted lambdas, `point-min' etc.  So I am still not convinced by this
argument, and I think in a similar other case it would not convince you as
well.

> >> Then again, we don't have such a "value returning vs not" duplication
> >> and associated convention for `let`, `progn`, `lambda`,
> >> `unwind-protect`, `catch`, `condition-case, ...
> >>
> >> The fact we have all three of if/when/and is not a good justification
> >> for `and-let*`.
> >
> > if/when/let are a bit different than the constructs in your list because
> > the values in conditionals have different semantics when interpreted as
> > a conditional than as an value or object.  This is part of the reason.
>
> I don't see the "different semantics" you're alluding to, I'm afraid.
> Can you explain what you mean?

The constructs you mentioned evaluate a sequence of expressions or
create bindings etc.  `if-let' and `when-let' are conditionals, the
first argument is a condition, interpreted as boolean.  Second,
`and-let' is something that _returns_ a "condition value", a boolean.
Therefore, the return value is also always significant.

OTOH, `when-let' executes expressions when some condition(s) are met.
The return value is not significant most of the time, but in particular
not when the condition was not met.  To rely on the implicit `nil'
return value of `when-let' to use it in a condition is not good style
IMHO.  Like relying on the nil return value of `while'.  You can do it
and "it's clear" but I hate it.  Ok?

> It wouldn't change anything to the readability of the code, AFAICT.
> In both cases the preceding `if` makes it immediately clear that we're
> interested in the final return value but only in whether it's nil
> or not.

Well, it does for me.  "It's obvious" or "its clear" is the way to less
readable code.  You replace a syntax where it is clear that the result
is a boolean with one where the meaning is context dependent.  Exactly
this is one of the things that worsen readability: the meaning of an
expression is not clear per se but becomes only clear by looking at the
outer context.

So, if `and-let' would be removed I would replace it with either
(if-let (TESTS...) BOOL-EXP nil) or
(let (VARS) (and (setq VAR1 TEST1) ...)).
If this is so much better for users like you I don't know.  It's
surely still worse for me.

There is a third option btw: remove `when-let' instead of `and-let'.
Since `when-let' is mostly `if-let' with a only a tiny difference that
doesn't let you do anything new...people not really obey using `when'
when there is no "else"...it's so similar to `and-let'... most of your
arguments are transferable 1:1.

Michael.