From: Psionic K <psionik@positron.solutions>
To: Emacs developers <emacs-devel@gnu.org>
Subject: cond* Examples
Date: Mon, 6 Jan 2025 23:55:09 +0900 [thread overview]
Message-ID: <CADQMGASN_MGmW0E6d8uAf_SczGaosM803vwACYQ9fD70pxBTHg@mail.gmail.com> (raw)
I'm putting together some examples on Elisp forms and wanted to get
ahead regarding use cases where cond* is more ergonomic.
The closest example I can relate from other languages is a Rust match
statement, which both destructures and binds before taking one
matching arm. Since cond-star's package docs say it's a replacement
for `pcase', that explanation is consistent at a surface level.
Regarding `bind*':
> it counts as true if the first binding's value is non-nil.
This feels inconsistent with `when-let*' and `if-let*' behavior, where
there's an intuitive reason that every bind must succeed for the first
or all body forms to evaluate. Is this a first-pass tradeoff?
Regarding exit clauses
> and it exits the `cond*'
From this, I expected the next part:
> If a clause has only one element, or if its first element is
> t, or if it ends with the keyword :non-exit, then
> this clause never exits the `cond*' construct. Instead,
> control falls through to the next clause (if any).
> The bindings made in CONDITION for the BODY of the non-exit clause
> re passed along to the rest of the clauses in this `cond*' construct.
Yeah, okay, so we're definitely evaluating multiple BODYs in some cases.
I read the tests, new manual section, and news. I couldn't find the
mailing list entries since I didn't subscribe and while I'm positive
I've seen many cond* threads, no query that I provided Namazu was
effective.
In any case, the goal is to identify 1) the point where cond* becomes
necessary. For example, in the case of let*, I can say that whenever
bindings become dependent, it is necessary to use let*. 2) where
cond* becomes advantageous. For example, when using let* over its
equivalent sequentially nested let form, the advantage is readily
evident in the reduction of form repetition. It's natural that
necessity and advantage tend to go together here.
From what I can gather and deduce, cond* is a variation of a cond
where I want to compose several destructurings into the same scope,
conditionally, so the equivalent in Elisp today will compose several
logic and pcase expressions, and this may lead to some repetitive
binding until the natural flow of the logic is discovered. While
cond* seems capable of short-circuiting this repetition by propagating
binds, I am less clear on natural cases where I want to bind from an
inner rather than outer form. Compared to let*, the existence of many
inner macro calls makes me wonder what I am compressing out. Why not
a sequential match* for such a composition of dependent destructuring
binds and then no repetition of match* in the inner forms?
In fact, I fear the use of cond* for its expression of both logic and
destructuring within one macro will obfuscate the purpose of why it
was employed. It does almost everything. As for what is not
included, it can't be used for looping except as an inner form. How
intensely jealous I am of Clojure, Rust, and Python, where
destructuring is quite natural in the other elementary forms,
including iteration, logic, and binding.
I do sense some idea trying to get out. If the destructuring form is
not understood by let, let*, if-let* etc, then we are forced to choose
between destructuring and logic. Other languages are blessed with
both and profit greatly from it. Cond does seem to be reaching
towards such a composition.
One idea I like from cond* (at least described in the documentation
that I was unable to find in the implementation of) is this notion
that the form is limited to comprehending other symbols bearing the
"cond-star property" as clauses.
It all makes me intensely jealous of languages for which every
conditional binding or iterative binding form can also destructure.
What a magical world if let, while-let, and if-let could destructure
and if let itself could be composed with a conditional expression
without a distinct macro such as the one named if-let.
If only there was a tool to dispense with redundant parentheses around
inner calls to further macros.
reply other threads:[~2025-01-06 14:55 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CADQMGASN_MGmW0E6d8uAf_SczGaosM803vwACYQ9fD70pxBTHg@mail.gmail.com \
--to=psionik@positron.solutions \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).