From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: arthur miller Newsgroups: gmane.emacs.devel Subject: Sv: Is this a bug in while-let or do I missunderstand it? Date: Sun, 10 Nov 2024 19:49:00 +0000 Message-ID: References: <86ldxrliau.fsf@gnu.org> <86ttcfv0bc.fsf@fastmail.fm> Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="_000_DU2PR02MB10109373D5E48CFFBD2618000965F2DU2PR02MB10109eu_" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="39320"; mail-complaints-to="usenet@ciao.gmane.io" Cc: "eliz@gnu.org" , "yuri.v.khan@gmail.com" , "emacs-devel@gnu.org" To: "Alfred M. Szmidt" , Joost Kremers Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Nov 10 21:20:31 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 1tAEQ9-000A2p-QQ for ged-emacs-devel@m.gmane-mx.org; Sun, 10 Nov 2024 21:20:30 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tAEPa-00086r-9g; Sun, 10 Nov 2024 15:19:54 -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 1tADvn-0004Er-M9 for emacs-devel@gnu.org; Sun, 10 Nov 2024 14:49:07 -0500 Original-Received: from mail-am6eur05olkn2109.outbound.protection.outlook.com ([40.92.91.109] helo=EUR05-AM6-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tADvl-0005yZ-5H; Sun, 10 Nov 2024 14:49:07 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=AFV6C0qp9JWwePa0yGoSLWC72SbQZViNkPtDMM2hALzhWrc/s1l56LklM2TakNpz7Wd9j+Pm7ryfmbKr9LqBhiNehvQg569RkMh6Z/vkZu5rcNx9pdbPKgTNyhxvn4Eml2YI6QBoiCwvinswjtaya+NXQ/iIdyD3lk/z/A2AhAdsrAZXYKP3sTaeM1kU//WlnLZGb0FdoKWnkt/s3EkUHX3P1BnUqYRVeydLfcYZ4WIgBWRaNBPmZvFlAxtb27Eg5+VRur/UFt9Zax5/O/Jof1jZmcYB3NzS9lxj5L7Xz2iF3JEwXqkfQ3GhAzQMhD017mQ6BQN2iaLLCo6amwSmvA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=u4CaGdQpIpDw8cbDWzS5yW2U8DXWrTTI+NdoguCPhDY=; b=Ng8aY/CbZNum0CXkGgpdNkqaAyK1PA3UPvrrsRDOpflY4fGVXviPWaT1dN4m0UdDg7OZmPDZUJ8K94nfoiungJiyBbRFf864KB200YDVeUAkKJresAcTuFhOdpTHa40ot5TRnQW+nxRQm5s/TH/KVXLI3Pv4sQvwm7nsJfvavq6455gFBb6xgfWBTdVsjdvg3QUmCf3+agjXw/VyKu22yzIFekXkdYq644II5JvlkXC+EOEV4l6TOWHqSfA2tuIq3qWj4CDm0AlQ+J4o9fipkWAuOID5NH/NbtGcAqEC47n8E6g3MkkLp1mamMSMbrWYCFKXyqWjfgF06JmuGLMIKQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=live.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=u4CaGdQpIpDw8cbDWzS5yW2U8DXWrTTI+NdoguCPhDY=; b=kQ3TyC4t1yZknnhWSPsulCgCcceQ/PA9NATBsBQuxF7atk2oXKtunz8EjUWv1hOAeGPEWdlr9aWTpEfeOebe1S+q7JNRIUgFiRiaONX8+FDCypUb4X/y+Up+declBKxsiUSdmuYcakX3Vfd2AYHC1XUz5eUbF2e57iKOH0zKHudMVV0Ciw8IFR4P1KkiJoTwAvGSrqig6jei7IA5wMgPHMrJafu7EeMNSPmY1Uduc8bYORGxuP25Gr20LzSy6+U0L4NaHA3QP3Mvs/76zrVyKX8FRjtlpINNkSQb6eaJyPd6iIRrjlDMxgpJnT/dcPX3ETHEuGYom57edBDXyFm+xg== Original-Received: from DU2PR02MB10109.eurprd02.prod.outlook.com (2603:10a6:10:497::14) by PAXPR02MB7840.eurprd02.prod.outlook.com (2603:10a6:102:288::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8137.20; Sun, 10 Nov 2024 19:49:00 +0000 Original-Received: from DU2PR02MB10109.eurprd02.prod.outlook.com ([fe80::f3c9:d4cb:290:d487]) by DU2PR02MB10109.eurprd02.prod.outlook.com ([fe80::f3c9:d4cb:290:d487%4]) with mapi id 15.20.8137.027; Sun, 10 Nov 2024 19:49:00 +0000 Thread-Topic: Is this a bug in while-let or do I missunderstand it? Thread-Index: AQHbMfbIoZNom93mHkmQsSTvSCnRb7Kur/AAgAA0XUGAAAq2gIAAAU7JgAAF/YCAAAA4e4AABg0AgAApz0+AAEHNJ4AApbaGgABIMiOAABkNP4AAcq4v In-Reply-To: Accept-Language: sv-SE, en-US Content-Language: sv-SE x-ms-exchange-messagesentrepresentingtype: 1 x-ms-publictraffictype: Email x-ms-traffictypediagnostic: DU2PR02MB10109:EE_|PAXPR02MB7840:EE_ x-ms-office365-filtering-correlation-id: c3d630e9-4c68-4e38-82d2-08dd01c0b902 x-microsoft-antispam: BCL:0; ARA:14566002|15030799003|461199028|19110799003|8060799006|8062599003|15080799006|7092599003|3412199025|440099028|102099032|56899033; x-microsoft-antispam-message-info: =?iso-8859-1?Q?3/XvUorOjSRFNwxM3HPUmrc5w9rq7FmWJbhxwgr72sbEwwhcQKAvHb58UW?= =?iso-8859-1?Q?TRT+Hjspx6sOgVCBKbPZu+kFLTHXLu/WwoBRhbDOm9iyNuyxMmAPw3X1Xe?= =?iso-8859-1?Q?doUcfXVsfAHDdeVSNYm4CFmxSo0FXW0q4q0BA/fcaQO/P6XtY3Tqs6qfHv?= =?iso-8859-1?Q?f+0Ju+vkCymEXyEdDNx3+bLYzEEUhqkN+Ykbgf44dy2sy6ud81PYdkmt7v?= =?iso-8859-1?Q?gm9i+VKCQkDZ4v90tQb9nLoHbDxHMnXRJOcI5pqgRgAO/y7ikFqVvLodA2?= =?iso-8859-1?Q?ihtsfIYTlb2Gb0WG647LISMX4f8n7eHbvAki+9czmwDoOFjzUcQhqHf4j0?= =?iso-8859-1?Q?NpDEReDTRpGwnVZ38glZmJJb407+sdnwM5n/sR4KS7D9H4cgmHS1hxw67E?= =?iso-8859-1?Q?t1XXxki5ToaMmI/L5yR9iuK4bYPRMugPkBVvdV9mZT61PM+yTGWjz9fttQ?= =?iso-8859-1?Q?BjAP4H+dqqcHF5SalOIvsuDxlJvYGpQUw94U9NE29LrV2CDES5YuUSkXwV?= =?iso-8859-1?Q?UxiHJj84u5MpSW8ty3CJc+2aSlvAvJIreHHx5jIWKXKeFdXghKyC5NbIBj?= =?iso-8859-1?Q?MyYG4cZLs+ujR5edQLfUnVTLwNjAxZgqv71trLMmF0nyw7dbvBrkrjr1KF?= =?iso-8859-1?Q?F45 x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?Q?9pliNO1NcZbXwTfLEyezaJPh2OBOKmwEvys+PBq9fe/dsJCzJb0awGW7U/?= =?iso-8859-1?Q?9YLvFVR6MjKxd9BhVwC2HatXHP1rJPla+Nl44Cg2Rh28KC8yDyGVK+EzGb?= =?iso-8859-1?Q?foTs/VhOb+uHpGBMdiFR+o7ydXrtQhJCHfuxBul1CTAesDeB9lTYK3ZiQr?= =?iso-8859-1?Q?zjo+RFoq4D7l3ihukY00rk0rMDKsbPRhGT9seeCj0kctTuhYxI1KNjIcKh?= =?iso-8859-1?Q?p8oeuWanH4MLajQDOTmIuQbhkSESpNRK8pE4Bddn1Cn+JIK/Vsq3EV3pgh?= =?iso-8859-1?Q?OB4gSFsxDQ8UYo0Jj5iBXP9XlydTb9V9OudnNwWsyWbj9F4Oa+PoiB3Y1A?= =?iso-8859-1?Q?nGmG0IyU6SptMCBYu39oGZZRriiOY7uzvMQCr2AuvGCI1t8jF1dvqlPdLh?= =?iso-8859-1?Q?nc1l+MfRjh8iA9UvXl/iHeph0a7z2dRaf+3IN+cVX7rjS4/IDCJY4Zhz0s?= =?iso-8859-1?Q?jdRW9qadqP5fln5UTmevzpjtnYhONithGIhkiTh1OlQof6OUAzw51tqy4d?= =?iso-8859-1?Q?CPDxt0CnWArQNTD8gI6YqVSLCg4DGFtOnJbz0WcoESC2txKCtEt+MHGgXC?= =?iso-8859-1?Q?ZteDXDPgObvpgzGgTw9r5P6j13hIPGXyR6odWwAR6GxNZGAAKLCeoliNLY?= =?iso-8859-1?Q? X-OriginatorOrg: sct-15-20-7828-19-msonline-outlook-12d23.templateTenant X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DU2PR02MB10109.eurprd02.prod.outlook.com X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: c3d630e9-4c68-4e38-82d2-08dd01c0b902 X-MS-Exchange-CrossTenant-originalarrivaltime: 10 Nov 2024 19:49:00.5725 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR02MB7840 Received-SPF: pass client-ip=40.92.91.109; envelope-from=arthur.miller@live.com; helo=EUR05-AM6-obe.outbound.protection.outlook.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 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, FREEMAIL_REPLY=1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.743, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sun, 10 Nov 2024 15:19:49 -0500 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:325388 Archived-At: --_000_DU2PR02MB10109373D5E48CFFBD2618000965F2DU2PR02MB10109eu_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable > @defmac while-let spec then-forms... > Like @code{when-let*}, but repeat until a binding in @var{spec} is > @code{nil}. The return value is always @code{nil}. > >The "Like FOO" is confusing -- it is not like when-let*, when-let* is >also not like let*. E.g., when spec is (binding value) or just >(value) (!?) -- which should be mentioned in the manual. > >These foo-LET are are mixing up the condition being tested and the >binding, when there is no binding the form seems to be just a test as >if you'd pass it directly to WHEN (or whatever). There should be some >example that SPEC is not at all like in LET, and that: > >(when-let* ((result1 (do-computation)) > ( (do-more result1))) > (do-something result1)) > >is something like (I guess?): > >(let ((result1 (do-computation))) > (when result1 > (when (do-more result1) > (do-something result2)))) > >And these mentions of "Like LET*" should be removed entierly. > >But this is a better, and a good start. > > @code{while-let} replaces a common pattern in which a binding is > established outside the @{while}-loop, tested as part of the condition = of > @{while} and subsequently changed inside the loop using the same expres= sion > that it was originally bound to: > > @example > (let ((result (do-computation))) > (while result > (do-stuff-with result) > (setq result (do-computation)))) > @end example > > Using @code{while-let}, this can be written more succinctly as: > > @example > (while-let ((result (do-computation))) > (do-stuff-with result)) > @end example > > The binding of @code{result} is reestablished at every iteration, there= fore > setting the value of @code{result} inside the loop has no effect. In or= der > to end the loop, @code{(do-computation)} should eventually return > @code{nil}. > > This example uses a single binding for clarity, but obviously > @code{while-let} can establish multiple bindings. The loop runs as long= as > all bindings are non-@code{nil}. > @end defmac > ``` > > Am I mistaken or is `while-let` a bit like a do..until loop that some > languages offer? Isn't it also like named-let? But without the ability to call itself recurs= ivey. I haven't tried it yet, but seems like while-let is a special case of named= -let, an "anonymous named-let" with conditions passed as-they-are. In other words= we could generate while-let as named-let with gensym as the name? (if cl-lib was all= owed in subr.el so to say). I am not sure if I have done it correctly, probably not= , but here is a try: (defmacro while-test (spec &rest body) (declare (indent defun)) (let* ((name (gensym "while-let-")) (bindings (if (and (consp spec) (symbolp (car spec))) (list spec) spec))) `(named-let ,name ,spec ,@body (if (not (and ,@(mapcar #'car bindings))) nil (,name ,@(mapcar #'cadr bindings)))))) ________________________________ Fr=E5n: Alfred M. Szmidt Skickat: den 10 november 2024 13:10 Till: Joost Kremers Kopia: eliz@gnu.org ; arthur.miller@live.com ; yuri.v.khan@gmail.com ; emacs-devel@gnu.or= g =C4mne: Re: Is this a bug in while-let or do I missunderstand it? @defmac while-let spec then-forms... Like @code{when-let*}, but repeat until a binding in @var{spec} is @code{nil}. The return value is always @code{nil}. The "Like FOO" is confusing -- it is not like when-let*, when-let* is also not like let*. E.g., when spec is (binding value) or just (value) (!?) -- which should be mentioned in the manual. These foo-LET are are mixing up the condition being tested and the binding, when there is no binding the form seems to be just a test as if you'd pass it directly to WHEN (or whatever). There should be some example that SPEC is not at all like in LET, and that: (when-let* ((result1 (do-computation)) ( (do-more result1))) (do-something result1)) is something like (I guess?): (let ((result1 (do-computation))) (when result1 (when (do-more result1) (do-something result2)))) And these mentions of "Like LET*" should be removed entierly. But this is a better, and a good start. @code{while-let} replaces a common pattern in which a binding is established outside the @{while}-loop, tested as part of the condition o= f @{while} and subsequently changed inside the loop using the same express= ion that it was originally bound to: @example (let ((result (do-computation))) (while result (do-stuff-with result) (setq result (do-computation)))) @end example Using @code{while-let}, this can be written more succinctly as: @example (while-let ((result (do-computation))) (do-stuff-with result)) @end example The binding of @code{result} is reestablished at every iteration, theref= ore setting the value of @code{result} inside the loop has no effect. In ord= er to end the loop, @code{(do-computation)} should eventually return @code{nil}. This example uses a single binding for clarity, but obviously @code{while-let} can establish multiple bindings. The loop runs as long = as all bindings are non-@code{nil}. @end defmac ``` Am I mistaken or is `while-let` a bit like a do..until loop that some languages offer? -- Joost Kremers Life has its moments --_000_DU2PR02MB10109373D5E48CFFBD2618000965F2DU2PR02MB10109eu_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable
>   @defmac while-let spec then-forms...
>   Like @code{when-let*}, but repeat until a binding in @var{spec}= is
>   @code{nil}.  The return value is always @code{nil}.
>
>The "Like FOO" is confusing -- it is not like when-let*, when= -let* is
>also not like let*.  E.g., when spec is (binding value) or just
>(value) (!?) -- which should be mentioned in the manual.
>
>These foo-LET are are mixing up the condition being tested and the
>binding, when there is no binding the form seems to be just a test as
>if you'd pass it directly to WHEN (or whatever).  There should be = some
>example that SPEC is not at all like in LET, and that:
>
>(when-let* ((result1 (do-computation))
>            (        = (do-more result1)))
>  (do-something result1))
>
>is something like (I guess?):
>
>(let ((result1 (do-computation)))
>  (when result1
>    (when (do-more result1)
>      (do-something result2))))
>
>And these mentions of "Like LET*" should be removed entierly.=
>
>But this is a better, and a good start.
>
>   @code{while-let} replaces a common pattern in which a binding i= s
>   established outside the @{while}-loop, tested as part of the co= ndition of
>   @{while} and subsequently changed inside the loop using the sam= e expression
>   that it was originally bound to:
>
>   @example
>   (let ((result (do-computation)))
>     (while result
>       (do-stuff-with result)
>       (setq result (do-computation))))
>   @end example
>
>   Using @code{while-let}, this can be written more succinctly as:=
>
>   @example
>   (while-let ((result (do-computation)))
>     (do-stuff-with result))
>   @end example
>
>   The binding of @code{result} is reestablished at every iteratio= n, therefore
>   setting the value of @code{result} inside the loop has no effec= t. In order
>   to end the loop, @code{(do-computation)} should eventually retu= rn
>   @code{nil}.
>
>   This example uses a single binding for clarity, but obviously
>   @code{while-let} can establish multiple bindings. The loop runs= as long as
>   all bindings are non-@code{nil}.
>   @end defmac
>   ```
>
>   Am I mistaken or is `while-let` a bit like a do..until loop tha= t some
>   languages offer?

Isn't it also like named-let? But without the ability to call itself recurs= ivey.
I haven't tried it yet, but seems like while-let is a special case of named= -let,
an "anonymous named-let" with conditions passed as-they-are. In o= ther words we could
generate while-let as named-let with gensym as the name? (if cl-lib was all= owed in
subr.el so to say). I am not sure if I have done it correctly, probably not= , but here
is a try:

(defmacro while-test (spec &rest body)
  (declare (indent defun))
  (let* ((name (gensym "while-let-"))
         (bindings (if (and (consp spec) (symbolp = (car spec)))
                     = ;  (list spec)
                     = ;spec)))
    `(named-let ,name ,spec
       ,@body
       (if (not (and ,@(mapcar #'car bindings)))
           nil
           (,name ,@(mapcar #'cadr bindings))= ))))

Fr=E5n: Alfred M. Szmidt &l= t;ams@gnu.org>
Skickat: den 10 november 2024 13:10
Till: Joost Kremers <joostkremers@fastmail.fm>
Kopia: eliz@gnu.org <eliz@gnu.org>; arthur.miller@live.com <= ;arthur.miller@live.com>; yuri.v.khan@gmail.com <yuri.v.khan@gmail.co= m>; emacs-devel@gnu.org <emacs-devel@gnu.org>
=C4mne: Re: Is this a bug in while-let or do I missunderstand it?
 
   @defmac while-let spec then-forms...<= br>    Like @code{when-let*}, but repeat until a binding in @var{spec= } is
   @code{nil}.  The return value is always @code{nil}.

The "Like FOO" is confusing -- it is not like when-let*, when-let= * is
also not like let*.  E.g., when spec is (binding value) or just
(value) (!?) -- which should be mentioned in the manual.

These foo-LET are are mixing up the condition being tested and the
binding, when there is no binding the form seems to be just a test as
if you'd pass it directly to WHEN (or whatever).  There should be some=
example that SPEC is not at all like in LET, and that:

(when-let* ((result1 (do-computation))
            ( &= nbsp;      (do-more result1)))
  (do-something result1))

is something like (I guess?):

(let ((result1 (do-computation)))
  (when result1
    (when (do-more result1)
      (do-something result2))))

And these mentions of "Like LET*" should be removed entierly.

But this is a better, and a good start.

   @code{while-let} replaces a common pattern in which a binding = is
   established outside the @{while}-loop, tested as part of the c= ondition of
   @{while} and subsequently changed inside the loop using the sa= me expression
   that it was originally bound to:

   @example
   (let ((result (do-computation)))
     (while result
       (do-stuff-with result)
       (setq result (do-computation))))
   @end example

   Using @code{while-let}, this can be written more succinctly as= :

   @example
   (while-let ((result (do-computation)))
     (do-stuff-with result))
   @end example

   The binding of @code{result} is reestablished at every iterati= on, therefore
   setting the value of @code{result} inside the loop has no effe= ct. In order
   to end the loop, @code{(do-computation)} should eventually ret= urn
   @code{nil}.

   This example uses a single binding for clarity, but obviously<= br>    @code{while-let} can establish multiple bindings. The loop run= s as long as
   all bindings are non-@code{nil}.
   @end defmac
   ```

   Am I mistaken or is `while-let` a bit like a do..until loop th= at some
   languages offer?


   --
   Joost Kremers
   Life has its moments


--_000_DU2PR02MB10109373D5E48CFFBD2618000965F2DU2PR02MB10109eu_--