all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: JD Smith <jdtsmith@gmail.com>
To: rms@gnu.org
Cc: Alan Mackenzie <acm@muc.de>, emacs-devel@gnu.org
Subject: Re: Code for cond* - cond*-match, cond*-subpat and backtrack-aliases
Date: Mon, 29 Jan 2024 07:16:32 -0500	[thread overview]
Message-ID: <87FCC950-68F3-4BE1-9ADC-FE1AB6C2BEC9@gmail.com> (raw)
In-Reply-To: <E1rUIAz-0007X4-1l@fencepost.gnu.org>

[-- Attachment #1: Type: text/plain, Size: 2361 bytes --]

>>>>  (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))
> 
> On Friday I started looking at something along the same lines.  I sent
> two messages about it.  It has the same features as cond*, using a
> syntax something like the above.

In a separate subthread (and offline) I've been discussing a simple `cond-let', envisioned as part of the if/when-let family (it has no pattern matching capabilities).  It does, as you'd expect, offer local bindings for each clause.

> On Jan 28, 2024, at 10:19 PM, Richard Stallman <rms@gnu.org> wrote:
> 
> Here is the new version.  I made a test framework for it
> and have used that to verify a number of test cases.
> ...
> 
> `(bind* BINDINGS...)' means to bind BINDINGS (as if they were in `let*')
> for the body of the clause.  As a condition, it counts as true
> if the first binding's value is non-nil.  All the bindings are made
> unconditionally for whatever scope they cover.


I wonder why (bind*) evaluates only its first value to determine if the binding condition is true?  We already have macros which evaluate the "truth of a set of bindings": the members of the if-let family.  And they 

"Evaluate each binding in turn, as in ‘let*’, stopping if a binding value is nil.  If all are non-nil return the [final] value."

I would personally find this behavior for variables bound locally within clauses easier to remember and more useful.  Users will already be familiar with it (from if-let), and it supports plain (VALUE) "bindings" for when you'd like to mix actual variable bindings and other tests in a given clause's CONDITION.

Attached is a simple cond-let design (again, just a simple extension of if/when-let, no pattern matching).  You notice that rather than using any particular keyword sigil like :let or bind*, it simply checks if the CONDITION of a clause is a list-of-lists, in which case it is interpreted as a binding spec.  The only small addition to if/when-let's binding handling is for plain (CONDITION-BINDING-SPEC) clauses; in that case, if all binding values are non-nil, the final value is returned from cond-let.



[-- Attachment #2.1: Type: text/html, Size: 6802 bytes --]

[-- Attachment #2.2: cond-let.el --]
[-- Type: application/octet-stream, Size: 2876 bytes --]

;;; cond-let.el --- cond with bindings -*- lexical-binding: t; -*-
;; Copyright (C) 2024 J.D. Smith

;;; Commentary:
;; cond-let is a macro which combines the capabilities of cond with
;; those of if-let.  The structure is the same as a cond: a sequence
;; of (condition body) forms is evaluated one by one, with the first
;; non-nil condition causing the result of its associated body to be
;; returned.  In addition to normal cond-like conditions, cond-let
;; accepts binding-spec conditions which bind variables and test their
;; values, identical to the SPEC lists in if-let.  Example:
;;
;;     (cond-let
;;       ((> x 12) (transform-it x))
;; 
;;       (((var  (other-info x))
;;         (pval (plist-get val :prop))
;;         (     (< pval 99)))
;;        (+ pval x))
;; 
;;       (t 1))
;;
;; Thanks to Stefan Monnier for valuable feedback.
;;; Code:
(require 'seq)
(eval-when-compile 'cl-lib)

(defmacro cond-let (&rest clauses)
  "Try each clause until one succeeds, possibly binding variables within them.
Each of the CLAUSES looks like (CONDITION BODY...), where
CONDITION can be a normal expression, as in `cond', or a binding
spec of the type accepted by `if-let'.  A binding spec is simply
a list of lists of the form:

   ((SYMBOL VALUEFORM) (VALUEFORM) ...)

Note that, just as in `if-let', each element of a binding spec
can take either the form (SYMBOL VALUEFORM) or just (VALUEFORM),
if only the result is of interest.  A binding spec's value is the
value of its last evaluated VALUEFORM, which means that all
values in a binding spec must be non-nil for the associated
clause to succeed.  Each SYMBOL is bound inside subsequent
VALUEFORMs within the same binding spec, as well as in the
associated clause's body (and no other clauses).

The first clause for which CONDITION evaluates to non-nil
succeeds: the expressions in its BODY are evaluated and the last
one's value becomes the value of the `cond-let' form.

If a clause has only one element, as in (CONDITION), then as a
special case `cond-let' returns CONDITION’s value, if that is
non-nil.

If no clause succeeds, `cond-let' returns nil."
  (declare (indent defun)
	   (debug (&rest [&or ((&rest [&or symbolp (symbolp form) (form)]) body)
			      (form body)])))
  (let ((cond-let (gensym "cond-let")))
    `(catch ',cond-let
       ,@(cl-loop
	  for (condition . body) in clauses
	  for clol = (and (consp condition) (consp (cdr condition))
			  (seq-every-p #'consp condition)) ; list-o-lists
	  if body collect
	  `(,(if clol 'when-let* 'when) ,condition
	    (throw ',cond-let ,(macroexp-progn body)))
	  else collect
	  (let ((clc (gensym "cond-let-cond")))
	    `(when-let* ((,clc ,(if clol `(and-let* ,condition) condition)))
	       (throw ',cond-let ,clc)))))))

(provide 'cond-let)
;;; cond-let.el ends here

[-- Attachment #2.3: Type: text/html, Size: 212 bytes --]

  reply	other threads:[~2024-01-29 12:16 UTC|newest]

Thread overview: 134+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-18  3:37 Code for cond* Richard Stallman
2024-01-18  4:59 ` Emanuel Berg
2024-01-20  3:39   ` Richard Stallman
2024-01-24 12:37     ` Po Lu
2024-01-24 19:12     ` Alan Mackenzie
2024-01-27  3:35       ` Richard Stallman
2024-01-18 15:44 ` Andrea Corallo
2024-01-19 10:42   ` João Távora
2024-01-21  3:04     ` Richard Stallman
2024-01-21 20:05       ` Adam Porter
2024-01-22  5:32         ` tomas
2024-01-23 13:39         ` Richard Stallman
2024-01-24  6:02           ` Po Lu
2024-01-24  9:48       ` Stefan Kangas
2024-01-24 10:09         ` Emanuel Berg
2024-01-24 11:30         ` João Távora
2024-01-24 12:08           ` João Távora
2024-01-24 12:09         ` Po Lu
2024-01-24 12:22           ` Ihor Radchenko
2024-01-24 12:33             ` Po Lu
2024-01-24 13:34               ` Ihor Radchenko
2024-01-24 13:52                 ` João Távora
2024-01-24 14:31                   ` Po Lu
2024-01-27  3:35                   ` Richard Stallman
2024-01-27  3:35                   ` Richard Stallman
2024-01-24 14:07                 ` Po Lu
2024-01-24 14:20                   ` Ihor Radchenko
2024-01-24 14:34                     ` Po Lu
2024-01-24 14:44                       ` Ihor Radchenko
2024-01-24 14:47                         ` João Távora
2024-01-24 15:28                         ` Emanuel Berg
2024-01-24 16:30                           ` Ihor Radchenko
2024-01-24 16:34                             ` Emanuel Berg
2024-01-25  9:06                           ` Po Lu
2024-01-25  9:55                             ` Alfred M. Szmidt
2024-01-25 10:38                               ` Eli Zaretskii
2024-01-25 11:29                               ` Po Lu
2024-01-25 12:04                                 ` Emanuel Berg
2024-01-25 13:32                                   ` Po Lu
2024-01-25 14:08                                     ` Emanuel Berg
2024-01-25 13:19                                 ` Alfred M. Szmidt
2024-01-25 13:43                                   ` Emanuel Berg
2024-01-25 14:31                                     ` Eli Zaretskii
2024-01-25 15:02                                       ` Emanuel Berg
2024-01-25 15:29                                         ` Eli Zaretskii
2024-01-25 15:33                                           ` Alfred M. Szmidt
2024-01-25 15:50                                             ` Eli Zaretskii
2024-01-25 16:01                                               ` Alfred M. Szmidt
2024-01-25 16:13                                                 ` Eli Zaretskii
2024-01-25 15:40                                           ` Emanuel Berg
2024-01-25 10:30                             ` Eli Zaretskii
2024-01-25 11:27                               ` Emanuel Berg
2024-01-24 12:15         ` Alan Mackenzie
2024-01-24 12:28           ` Emanuel Berg
2024-01-25  9:10           ` Po Lu
2024-01-25 11:56             ` Emanuel Berg
2024-01-25 13:21               ` Po Lu
2024-01-25 13:56                 ` Emanuel Berg
2024-01-25 23:32           ` Stefan Kangas
2024-01-20  3:39   ` Richard Stallman
2024-01-23 18:10 ` Stefan Monnier via Emacs development discussions.
2024-01-24  4:49   ` JD Smith
2024-01-24  9:45     ` Stefan Kangas
2024-01-24 15:29       ` JD Smith
2024-01-24 15:55         ` Stefan Monnier
2024-01-24 16:02           ` Stefan Monnier
2024-01-24 16:20           ` JD Smith
2024-01-24 17:08             ` Stefan Monnier
2024-01-24 16:35           ` [External] : " Drew Adams
2024-01-24 16:30     ` Drew Adams
2024-02-01  8:56       ` Madhu
2024-02-01 22:46         ` Emanuel Berg
2024-01-25  3:16     ` Madhu
2024-01-25 13:57       ` Stefan Monnier
2024-01-25 15:17         ` JD Smith
2024-01-25 15:37           ` JD Smith
2024-01-25 15:44             ` Alfred M. Szmidt
2024-01-25 16:00               ` JD Smith
2024-01-25 16:05               ` Stefan Monnier
2024-01-25 16:12                 ` Alfred M. Szmidt
2024-01-25 16:20                   ` Stefan Monnier
2024-01-25 16:33                   ` JD Smith
2024-01-29  3:19             ` Richard Stallman
2024-01-26  4:30   ` Richard Stallman
2024-01-28  3:06     ` Stefan Monnier via Emacs development discussions.
2024-01-30  3:59       ` Richard Stallman
2024-01-30 13:02         ` Stefan Monnier
2024-02-23  3:04           ` Richard Stallman
2024-01-26  4:30   ` Richard Stallman
2024-01-28  4:16     ` Stefan Monnier via Emacs development discussions.
2024-01-31  3:32       ` Richard Stallman
2024-01-31 13:20         ` Stefan Monnier
2024-02-03  3:32           ` Richard Stallman
2024-02-03  6:09             ` Stefan Monnier
2024-02-03  6:48               ` Emanuel Berg
2024-02-04  4:46               ` Richard Stallman
2024-02-04 14:04                 ` Stefan Monnier
2024-02-04  4:46               ` Richard Stallman
2024-02-04 13:58                 ` Stefan Monnier
2024-02-13  0:48                 ` Stefan Monnier
2024-02-13  2:27                   ` Stefan Monnier
2024-02-14 11:16                   ` Richard Stallman
2024-02-14 12:45                     ` Stefan Monnier
2024-02-22  3:05                       ` Richard Stallman
2024-02-22  4:08                         ` Stefan Monnier
2024-02-25  3:14                           ` Richard Stallman
2024-02-25 15:03                             ` Stefan Monnier
2024-02-29  3:50                               ` Richard Stallman
2024-02-29 18:07                                 ` Stefan Monnier
2024-02-29  3:50                               ` Richard Stallman
2024-02-13  0:41         ` Stefan Monnier
2024-02-23  3:04           ` Richard Stallman
2024-02-23 13:39             ` Stefan Monnier
2024-02-25  3:16               ` Richard Stallman
2024-02-25 14:57                 ` Alfred M. Szmidt
2024-02-25 15:38                   ` Stefan Monnier
2024-02-25 16:42                     ` Alfred M. Szmidt
2024-02-25 17:13                       ` Stefan Monnier
2024-02-25 17:22                     ` Alan Mackenzie
2024-02-25 17:46                       ` Alfred M. Szmidt
2024-02-25 18:13                         ` Stefan Monnier
2024-02-25 17:10                 ` Stefan Monnier
2024-02-27  3:11                   ` Richard Stallman
2024-01-24 12:39 ` Alan Mackenzie
2024-01-24 14:43   ` Emanuel Berg
2024-01-24 16:25   ` Manuel Giraud via Emacs development discussions.
2024-01-25 14:01   ` Code for cond* - cond*-match, cond*-subpat and backtrack-aliases Alan Mackenzie
2024-01-29  3:19     ` Richard Stallman
2024-01-29  8:54       ` Andreas Schwab
2024-01-29  3:19     ` Richard Stallman
2024-01-29 12:16       ` JD Smith [this message]
2024-02-01  3:51         ` Richard Stallman
2024-02-01 14:54           ` JD Smith
2024-02-04  4:42             ` Richard Stallman

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

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87FCC950-68F3-4BE1-9ADC-FE1AB6C2BEC9@gmail.com \
    --to=jdtsmith@gmail.com \
    --cc=acm@muc.de \
    --cc=emacs-devel@gnu.org \
    --cc=rms@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 external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.