From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: JD Smith Newsgroups: gmane.emacs.devel Subject: Re: Code for cond* - cond*-match, cond*-subpat and backtrack-aliases Date: Mon, 29 Jan 2024 07:16:32 -0500 Message-ID: <87FCC950-68F3-4BE1-9ADC-FE1AB6C2BEC9@gmail.com> References: Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3774.300.61.1.2\)) Content-Type: multipart/alternative; boundary="Apple-Mail=_A9E72A84-D6C6-45A7-836F-0F7EC831A5AA" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="22520"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Alan Mackenzie , emacs-devel@gnu.org To: rms@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Mon Jan 29 13:17:42 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rUQa5-0005fa-I9 for ged-emacs-devel@m.gmane-mx.org; Mon, 29 Jan 2024 13:17:41 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rUQZI-0000sd-2B; Mon, 29 Jan 2024 07:16:52 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rUQZG-0000sT-4s for emacs-devel@gnu.org; Mon, 29 Jan 2024 07:16:50 -0500 Original-Received: from mail-io1-xd33.google.com ([2607:f8b0:4864:20::d33]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rUQZE-0003zz-6A; Mon, 29 Jan 2024 07:16:49 -0500 Original-Received: by mail-io1-xd33.google.com with SMTP id ca18e2360f4ac-7bfe5aa702fso67393139f.3; Mon, 29 Jan 2024 04:16:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706530604; x=1707135404; darn=gnu.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=MGV1XwDvZQ/Y95tp1/A5JChi3tXRR45MGhGpkHvszLs=; b=H0QtfoZQIqbOofYcsoao4aDyyyvjLk00cQW6OrXdKa02vZ8vnZjTijErxN9qkPAsFr /ui1/z8mIyR6HxB3WkUuW6fkHWXYx9jyCye6/wTXmO9/XeSyboaqgmOlSqGrIMXZ6j1B AWtyR77/KAplAtOMcEueQlurPtmhIcNUTlSIZFSsau8me5DmFU/MWE8hW10RXCRt7tQJ 1IsWVwJCB2pcxBgQXQyxZ4MF4l9H951zTuL4Lq9BTg3bgeBC79QGqBnDLr9KyBDI6wrW AAAMY/iFyj8IAr4jDLc+VDRSGIvJRTG8zj+9HA2ypci+lzyR8xS7WnXUi1176dw5b8gN 9pNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706530604; x=1707135404; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=MGV1XwDvZQ/Y95tp1/A5JChi3tXRR45MGhGpkHvszLs=; b=neuDNmMyHIfCNLR5BNlb9FULHATBktaOOgiNFOWSiC9ae1XRQQZVcnXsABK8jzOfGx LgLp9FDwkElzEinSJFiX2NN9By82j70UzpZGBSg8MGG4HTiInk24QX2mWK81JqkoTmrs W+qGGgAeTvJ1gRbk9E5UPRkorpqAkLGzTMXqgvA4rlMt/E1VOhTREx+M7OmYpKZSeHik THydwUO/2CSUMrnRK6/bAC4uC404O67X9Jo/E+NYBixYl1naSs57jfRCO8LjbJ4T9//U IeAFPb+PXgvzqOAkNg+j+Imml/qh8bVJCkjO/nr00SHbCvOGb9U9s7NnhZAX0/SCAGl+ rEKQ== X-Gm-Message-State: AOJu0YzkguLQbkDKJbGhDlGrNqH2x2ah+Q8c5x8Cdx/td/HlPxOClugP nC8mFfQwhaCJY2SVNry68BexC9GORPcLKa5v9vOtZUKI3FFXtul990jgAT2l X-Google-Smtp-Source: AGHT+IE5ssQPTxd91AnQdFlZZs3Wo5M90YS9ITL/Bt33m89vZ0VlJS/rD1hbssj15RbK+YmJ8VhHTg== X-Received: by 2002:a6b:d90d:0:b0:7bf:96ab:e152 with SMTP id r13-20020a6bd90d000000b007bf96abe152mr7322977ioc.4.1706530604412; Mon, 29 Jan 2024 04:16:44 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCVY16MJgOSKMDsBYOLBjI1+tYRinzpFHYLwq1Y3qIp7cRmoFmkwNWcv2tLYbmApWNYVhpabAcuj5+6TL+fD/rA+ws4P Original-Received: from smtpclient.apple (cm-24-53-187-34.buckeyecom.net. [24.53.187.34]) by smtp.gmail.com with ESMTPSA id t6-20020a6b5f06000000b007bfd2f41f8csm1785280iob.3.2024.01.29.04.16.43 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Jan 2024 04:16:43 -0800 (PST) In-Reply-To: X-Mailer: Apple Mail (2.3774.300.61.1.2) Received-SPF: pass client-ip=2607:f8b0:4864:20::d33; envelope-from=jdtsmith@gmail.com; helo=mail-io1-xd33.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:315585 Archived-At: --Apple-Mail=_A9E72A84-D6C6-45A7-836F-0F7EC831A5AA Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 >>>> (my-cond >>>> (:let var value) >>>> (:let dvar (derived-from var)) >>>> ((has-the-right-stuff-p dvar) >>>> (cons 'correct dvar)) >>>>=20 >>>> (:let foo value2) >>>> (:let bar (1- foo)) >>>> ((< bar 0) >>>> (cons 'incorrect bar)) >>>>=20 >>>> (t nil)) >=20 > 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=E2=80=AFPM, Richard Stallman = wrote: >=20 > Here is the new version. I made a test framework for it > and have used that to verify a number of test cases. > ... >=20 > `(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=20 "Evaluate each binding in turn, as in =E2=80=98let*=E2=80=99, 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. =EF=BF=BC= --Apple-Mail=_A9E72A84-D6C6-45A7-836F-0F7EC831A5AA Content-Type: multipart/mixed; boundary="Apple-Mail=_CFF0274D-E7CE-4377-A2AA-23C821C349E0" --Apple-Mail=_CFF0274D-E7CE-4377-A2AA-23C821C349E0 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8
 (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=E2=80=AFPM, 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 =E2=80=98let*=E2=80=99, 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.

= --Apple-Mail=_CFF0274D-E7CE-4377-A2AA-23C821C349E0 Content-Disposition: attachment; filename=cond-let.el Content-Type: application/octet-stream; x-unix-mode=0644; name="cond-let.el" Content-Transfer-Encoding: quoted-printable ;;;=20cond-let.el=20---=20cond=20with=20bindings=20-*-=20= lexical-binding:=20t;=20-*-=0A;;=20Copyright=20(C)=202024=20J.D.=20Smith=0A= =0A;;;=20Commentary:=0A;;=20cond-let=20is=20a=20macro=20which=20combines=20= the=20capabilities=20of=20cond=20with=0A;;=20those=20of=20if-let.=20=20= The=20structure=20is=20the=20same=20as=20a=20cond:=20a=20sequence=0A;;=20= of=20(condition=20body)=20forms=20is=20evaluated=20one=20by=20one,=20= with=20the=20first=0A;;=20non-nil=20condition=20causing=20the=20result=20= of=20its=20associated=20body=20to=20be=0A;;=20returned.=20=20In=20= addition=20to=20normal=20cond-like=20conditions,=20cond-let=0A;;=20= accepts=20binding-spec=20conditions=20which=20bind=20variables=20and=20= test=20their=0A;;=20values,=20identical=20to=20the=20SPEC=20lists=20in=20= if-let.=20=20Example:=0A;;=0A;;=20=20=20=20=20(cond-let=0A;;=20=20=20=20=20= =20=20((>=20x=2012)=20(transform-it=20x))=0A;;=20=0A;;=20=20=20=20=20=20=20= (((var=20=20(other-info=20x))=0A;;=20=20=20=20=20=20=20=20=20(pval=20= (plist-get=20val=20:prop))=0A;;=20=20=20=20=20=20=20=20=20(=20=20=20=20=20= (<=20pval=2099)))=0A;;=20=20=20=20=20=20=20=20(+=20pval=20x))=0A;;=20=0A= ;;=20=20=20=20=20=20=20(t=201))=0A;;=0A;;=20Thanks=20to=20Stefan=20= Monnier=20for=20valuable=20feedback.=0A;;;=20Code:=0A(require=20'seq)=0A= (eval-when-compile=20'cl-lib)=0A=0A(defmacro=20cond-let=20(&rest=20= clauses)=0A=20=20"Try=20each=20clause=20until=20one=20succeeds,=20= possibly=20binding=20variables=20within=20them.=0AEach=20of=20the=20= CLAUSES=20looks=20like=20(CONDITION=20BODY...),=20where=0ACONDITION=20= can=20be=20a=20normal=20expression,=20as=20in=20`cond',=20or=20a=20= binding=0Aspec=20of=20the=20type=20accepted=20by=20`if-let'.=20=20A=20= binding=20spec=20is=20simply=0Aa=20list=20of=20lists=20of=20the=20form:=0A= =0A=20=20=20((SYMBOL=20VALUEFORM)=20(VALUEFORM)=20...)=0A=0ANote=20that,=20= just=20as=20in=20`if-let',=20each=20element=20of=20a=20binding=20spec=0A= can=20take=20either=20the=20form=20(SYMBOL=20VALUEFORM)=20or=20just=20= (VALUEFORM),=0Aif=20only=20the=20result=20is=20of=20interest.=20=20A=20= binding=20spec's=20value=20is=20the=0Avalue=20of=20its=20last=20= evaluated=20VALUEFORM,=20which=20means=20that=20all=0Avalues=20in=20a=20= binding=20spec=20must=20be=20non-nil=20for=20the=20associated=0Aclause=20= to=20succeed.=20=20Each=20SYMBOL=20is=20bound=20inside=20subsequent=0A= VALUEFORMs=20within=20the=20same=20binding=20spec,=20as=20well=20as=20in=20= the=0Aassociated=20clause's=20body=20(and=20no=20other=20clauses).=0A=0A= The=20first=20clause=20for=20which=20CONDITION=20evaluates=20to=20= non-nil=0Asucceeds:=20the=20expressions=20in=20its=20BODY=20are=20= evaluated=20and=20the=20last=0Aone's=20value=20becomes=20the=20value=20= of=20the=20`cond-let'=20form.=0A=0AIf=20a=20clause=20has=20only=20one=20= element,=20as=20in=20(CONDITION),=20then=20as=20a=0Aspecial=20case=20= `cond-let'=20returns=20CONDITION=E2=80=99s=20value,=20if=20that=20is=0A= non-nil.=0A=0AIf=20no=20clause=20succeeds,=20`cond-let'=20returns=20= nil."=0A=20=20(declare=20(indent=20defun)=0A=09=20=20=20(debug=20(&rest=20= [&or=20((&rest=20[&or=20symbolp=20(symbolp=20form)=20(form)])=20body)=0A=09= =09=09=20=20=20=20=20=20(form=20body)])))=0A=20=20(let=20((cond-let=20= (gensym=20"cond-let")))=0A=20=20=20=20`(catch=20',cond-let=0A=20=20=20=20= =20=20=20,@(cl-loop=0A=09=20=20for=20(condition=20.=20body)=20in=20= clauses=0A=09=20=20for=20clol=20=3D=20(and=20(consp=20condition)=20= (consp=20(cdr=20condition))=0A=09=09=09=20=20(seq-every-p=20#'consp=20= condition))=20;=20list-o-lists=0A=09=20=20if=20body=20collect=0A=09=20=20= `(,(if=20clol=20'when-let*=20'when)=20,condition=0A=09=20=20=20=20(throw=20= ',cond-let=20,(macroexp-progn=20body)))=0A=09=20=20else=20collect=0A=09=20= =20(let=20((clc=20(gensym=20"cond-let-cond")))=0A=09=20=20=20=20= `(when-let*=20((,clc=20,(if=20clol=20`(and-let*=20,condition)=20= condition)))=0A=09=20=20=20=20=20=20=20(throw=20',cond-let=20,clc)))))))=0A= =0A(provide=20'cond-let)=0A;;;=20cond-let.el=20ends=20here=0A= --Apple-Mail=_CFF0274D-E7CE-4377-A2AA-23C821C349E0 Content-Transfer-Encoding: 7bit Content-Type: text/html; charset=us-ascii
--Apple-Mail=_CFF0274D-E7CE-4377-A2AA-23C821C349E0-- --Apple-Mail=_A9E72A84-D6C6-45A7-836F-0F7EC831A5AA--