[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Code for cond*
|
From: |
JD Smith |
|
Subject: |
Re: Code for cond* |
|
Date: |
Thu, 25 Jan 2024 10:17:47 -0500 |
> On Jan 25, 2024, at 8:57 AM, Stefan Monnier <monnier@iro.umontreal.ca> wrote:
>
>>> [1] I regularly convince myself that it’s such low hanging fruit,
>>> there must in fact already BE a cond-let, and I go hunting for it.
>>> The obvious interface seems like such a straightforward extension of
>>> if/when-let, that there would be absolutely nothing new to learn:
>>>
>>> (cond-let
>>> (((var value)
>>> (dvar (derived-from var))
>>> ((has-the-right-stuff-p dvar)))
>>> (cons 'correct dvar))
>>>
>>> (((foo value2)
>>> (bar (1- foo))
>>> ((< bar 0)))
>>> (cons 'incorrect bar))
>>>
>>> (t nil))
>
> Nice. Would `var` and `dvar` scope over just the first branch or also the
> other ones?
> Technically, there is no reason for them not to be visible in the other
> branches, so that's what I would go for.
It seems most intuitive to me for each clause to have its own scope, but mostly
because active bindings made in sibling forms at the same depth seem
non-intuitive and easy to overlook.
> Personally, I was thinking of a syntax like
>
> (my-cond
> (:let var value)
> (:let dvar (derived-from var))
> ((has-the-right-stuff-p dvar)
> (cons 'correct dvar))
>
> (:let foo value2)
> (:let bar (1- foo))
> ((< bar 0)
> (cons 'incorrect bar))
>
> (t nil))
>
> with the intention of replacing `cond` without introducing
> any incompatibility.
This is an interesting approach, and makes it much clearer when new bindings
appear. Mine is a different idea. In my cond-let approach, just as for
when-let, each binding in a clause’s binding group is tested, one by one, and
the clause only succeeds if all the bindings are non-nil. So var and dvar must
be non-nil, and (has-the-right-stuff-p dvar) too. To ensure this, in your
version, I’d need something like:
(:let var value)
(:let dvar (and var (derived-from var))
((and var dvar (has-the-right-stuff-p dvar)) …)
This would get repetitive and error prone for a large number of bindings, not
to mention awkward if some “bindings” in the middle are actually
bound-variable-free tests like ((has-the-right-stuff-p dvar)).
The hypothetical cond-let makes it easy to build an arbitrary grouping of
sequential when's/when-let's which short circuit as soon as the first clause
body executes, no matter what that body returns.
So:
(cond-let
(simple0 body0) ; a normal cond-style clause
(bindings1 body1)
(bindings2 body2)
(bindings3 body3)
(t fallthrough-body))
would be equivalent to:
(catch 'cond-let
(when simple0 (throw 'cond-let body0))
(when-let (bindings1) (throw 'cond-let body1))
(when-let (bindings2) (throw 'cond-let body2))
(when-let (bindings3) (throw 'cond-let body3))
(throw 'cond-let fallthrough-body))
But a lot less wordy/repetitive ;).
- Re: Code for cond*, (continued)
- Re: Code for cond*, Stefan Kangas, 2024/01/24
- Re: Code for cond*, JD Smith, 2024/01/24
- Re: Code for cond*, Stefan Monnier, 2024/01/24
- Re: Code for cond*, Stefan Monnier, 2024/01/24
- Re: Code for cond*, JD Smith, 2024/01/24
- Re: Code for cond*, Stefan Monnier, 2024/01/24
- RE: [External] : Re: Code for cond*, Drew Adams, 2024/01/24
- RE: [External] : Re: Code for cond*, Drew Adams, 2024/01/24
- Re: Code for cond*, Madhu, 2024/01/25
- Re: Code for cond*, Stefan Monnier, 2024/01/25
- Re: Code for cond*,
JD Smith <=
- Re: Code for cond*, JD Smith, 2024/01/25
- Re: Code for cond*, Alfred M. Szmidt, 2024/01/25
- Re: Code for cond*, JD Smith, 2024/01/25
- Re: Code for cond*, Stefan Monnier, 2024/01/25
- Re: Code for cond*, Alfred M. Szmidt, 2024/01/25
- Re: Code for cond*, Stefan Monnier, 2024/01/25
- Re: Code for cond*, JD Smith, 2024/01/25
- Re: Code for cond*, Richard Stallman, 2024/01/28
Re: Code for cond*, Richard Stallman, 2024/01/25