From debbugs-submit-bounces@debbugs.gnu.org Sat Aug 29 05:41:53 2020 Received: (at submit) by debbugs.gnu.org; 29 Aug 2020 09:41:53 +0000 Received: from localhost ([127.0.0.1]:47932 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kBxMv-0003yG-BL for submit@debbugs.gnu.org; Sat, 29 Aug 2020 05:41:53 -0400 Received: from lists.gnu.org ([209.51.188.17]:39578) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kBxMt-0003y9-S4 for submit@debbugs.gnu.org; Sat, 29 Aug 2020 05:41:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46482) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kBxMt-0000ho-LF for bug-gnu-emacs@gnu.org; Sat, 29 Aug 2020 05:41:51 -0400 Received: from mail-oi1-x22a.google.com ([2607:f8b0:4864:20::22a]:42839) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kBxMr-0001eh-8p for bug-gnu-emacs@gnu.org; Sat, 29 Aug 2020 05:41:51 -0400 Received: by mail-oi1-x22a.google.com with SMTP id j7so2879872oij.9 for ; Sat, 29 Aug 2020 02:41:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=dK6piiH0w4fTvG90pSaLuk8/aojNP95rKv6u5SUG8pQ=; b=h9nm7P9RJTRJvKR+YXuX7A6nF8r66tksz290rhz+G7Vh7eWD4EMGHrg63bGgj7fHNC gfKruMHvtp8lXnl+KZHRdF+c4neKd1i/qtdh54yE5nWGdZUkcH6t1jnp7SVQqRM5c0iq 5VscWn1LxhI8dymJv3La02bCdYWN79iQJwJgrMNqfueOsxe0lQH/ANHCAHJtMcDqd0ij +dOQzpPxvUSbfJC9OpcqiSjDKL6KuvP9LAETL2PdVK+92lOSTfEwrpnpmFB1amblglGz m2i+PqjCHFb3QUyZyt84ec8dwpQ9QvMzVIH0jwIUs7FSTfmIhfeqAJ5AjZZsMeQYUCpc KCtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=dK6piiH0w4fTvG90pSaLuk8/aojNP95rKv6u5SUG8pQ=; b=ESj9eT4m3VXxTxFPcOTuzinvh8LJFdHf0capuig9aU42HmPjrAohPEuiVAGDXPU93o dDSuoZbhZP5+GqgY67mlnSS2mbBRQu/ZSvJFfDCmfc3rxAXcdPufxtROOxPz921IOoQX +0iFVEi/wPg82QZbF5kXpRTiC+z92fYN4l5bzyyugI1CX++elHus6sGFN8CmXHp+3tmM k5HkElHFhNhcvh9rUWdaBFyk820v1PM00GAhW+Ns5e0BMoREN5EnuKWNUoUNmEpbaSW9 UxSywtUxhQkr9lpA0VbtdoaXHD0BFBWbba8ncM0rSd8PeAkAF/pHrUcsRAQCL9G8Hvta NEqg== X-Gm-Message-State: AOAM533PqHG1/+LTvkAG6NF6Pybd4sMs9WG7Dygx318WmxK2GAGEXahf gL0ZHWtMEaVdn+rGj691xO7aBvy5ILC00jw4xAGgwKVYZZcPbg== X-Google-Smtp-Source: ABdhPJwLDjLfsV1ZGJLiV9atK38xh1xs2AlwoBX/u53KaO3L5hHWchsw/8NKoxvkCr/Kneb+BM7/tcO4EEr0++RTX8s= X-Received: by 2002:aca:dc04:: with SMTP id t4mr1612979oig.30.1598694107350; Sat, 29 Aug 2020 02:41:47 -0700 (PDT) MIME-Version: 1.0 From: Pip Cet Date: Sat, 29 Aug 2020 09:41:10 +0000 Message-ID: Subject: 28.0.50; pcase not binding variables conditionally To: bug-gnu-emacs@gnu.org, Stefan Monnier Content-Type: multipart/mixed; boundary="0000000000005fa99805ae00fa25" Received-SPF: pass client-ip=2607:f8b0:4864:20::22a; envelope-from=pipcet@gmail.com; helo=mail-oi1-x22a.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. 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, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: -0.1 (/) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.3 (--) --0000000000005fa99805ae00fa25 Content-Type: text/plain; charset="UTF-8" I'm having trouble with pcase's behavior. (pcase "a" ((or (pred symbolp) name) (let ((foo 'bar)) name))) throws an error. It shouldn't. (Note that the dummy "let" is necessary to force the pcase code generation to use a function call). I believe the culprit is the code around this comment in pcase.el ;; If some of `vars' were not found in `prevvars', that's ;; OK it just means those vars aren't present in all ;; branches, so they can be used within the pattern ;; (e.g. by a `guard/let/pred') but not in the branch. I believe that's incorrect: using the variable in a condition-case should work, as should conditional shadowing of an existing binding, as in this case: (let ((name "default")) (pcase "a" ((or (pred symbolp) name) name))) (which works), or this case: (let ((name "default")) (pcase "a" ((or (pred symbolp) name) (let ((foo 'bar)) name)))) (which doesn't). I believe the right fix is not to share code for the same branch if it uses different variables, as in the attached patch. It's possible this increases codegen complexity in some construed cases, but in practice that shouldn't be a problem. --0000000000005fa99805ae00fa25 Content-Type: text/x-patch; charset="US-ASCII"; name="0001-Allow-variable-bindings-to-differ-across-pcase-alter.patch" Content-Disposition: attachment; filename="0001-Allow-variable-bindings-to-differ-across-pcase-alter.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_kefh413x0 RnJvbSBlYzdlNGE5MmFiMDhhZGY0ZWIwMzZlYTUwZjdkNzBiYWRlNjM3MTliIE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiBQaXAgQ2V0IDxwaXBjZXRAZ21haWwuY29tPgpEYXRlOiBTYXQs IDI5IEF1ZyAyMDIwIDA5OjM1OjQxICswMDAwClN1YmplY3Q6IFtQQVRDSF0gQWxsb3cgdmFyaWFi bGUgYmluZGluZ3MgdG8gZGlmZmVyIGFjcm9zcyBwY2FzZSBhbHRlcm5hdGl2ZXMuCgpUaGlzIGZp eGVzIHBjYXNlIGNhc2VzIGxpa2UgKChvciAocHJlZCBzdHJpbmdwKSBuYW1lKSBuYW1lKSwgd2hp Y2gKc2hvdWxkIHVzZSB0aGUgcGNhc2UtbG9jYWwgYmluZGluZyBvbmx5IGlmIEVYUFZBTCBpc24n dCBhIHN0cmluZy4KCiogbGlzcC9lbWFjcy1saXNwL3BjYXNlLmVsIChwY2FzZS0tZXhwYW5kKTog RG8gbm90IHNoYXJlIGNvZGUgaWYKdmFyaWFibGVzIGRpZmZlci4KLS0tCiBsaXNwL2VtYWNzLWxp c3AvcGNhc2UuZWwgfCAzICsrLQogMSBmaWxlIGNoYW5nZWQsIDIgaW5zZXJ0aW9ucygrKSwgMSBk ZWxldGlvbigtKQoKZGlmZiAtLWdpdCBhL2xpc3AvZW1hY3MtbGlzcC9wY2FzZS5lbCBiL2xpc3Av ZW1hY3MtbGlzcC9wY2FzZS5lbAppbmRleCBhOGNlMjMyODRjLi43MjkxNjI5NmNiIDEwMDY0NAot LS0gYS9saXNwL2VtYWNzLWxpc3AvcGNhc2UuZWwKKysrIGIvbGlzcC9lbWFjcy1saXNwL3BjYXNl LmVsCkBAIC0zNDYsNyArMzQ2LDggQEAgcGNhc2UtLWV4cGFuZAogICAgICAgICAgICAgKGxhbWJk YSAoY29kZSB2YXJzKQogICAgICAgICAgICAgICAobGV0ICgodmFycyAocGNhc2UtLWZncmVwIHZh cnMgY29kZSkpCiAgICAgICAgICAgICAgICAgICAgIChwcmV2IChhc3NxIGNvZGUgc2VlbikpKQot ICAgICAgICAgICAgICAgIChpZiAobm90IHByZXYpCisgICAgICAgICAgICAgICAgKGlmIChvciAo bm90IHByZXYpCisgICAgICAgICAgICAgICAgICAgICAgICAobm90IChlcXVhbCAoY2FkciBwcmV2 KSB2YXJzKSkpCiAgICAgICAgICAgICAgICAgICAgIChsZXQgKChyZXMgKHBjYXNlLWNvZGVnZW4g Y29kZSB2YXJzKSkpCiAgICAgICAgICAgICAgICAgICAgICAgKHB1c2ggKGxpc3QgY29kZSB2YXJz IHJlcykgc2VlbikKICAgICAgICAgICAgICAgICAgICAgICByZXMpCi0tIAoyLjI4LjAKCg== --0000000000005fa99805ae00fa25-- From debbugs-submit-bounces@debbugs.gnu.org Sat Aug 29 08:02:04 2020 Received: (at 43100) by debbugs.gnu.org; 29 Aug 2020 12:02:04 +0000 Received: from localhost ([127.0.0.1]:47994 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kBzYa-0003PQ-83 for submit@debbugs.gnu.org; Sat, 29 Aug 2020 08:02:04 -0400 Received: from mail-ot1-f53.google.com ([209.85.210.53]:33860) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kBzYY-0003Ov-2K for 43100@debbugs.gnu.org; Sat, 29 Aug 2020 08:02:03 -0400 Received: by mail-ot1-f53.google.com with SMTP id k20so1549435otr.1 for <43100@debbugs.gnu.org>; Sat, 29 Aug 2020 05:02:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=nvsEnZ076OwdPyi/GUAK85QsSX+9bAobn4d23nIRRzE=; b=lpdeCS0C+zBXu3kACPTwHRVlqnRNhVG/zgOymnn+V5nWZcTJXK6XPADFNuegRb2ON0 38HFMJr2WUFk47OWbLrey0PNX8uOmOTFZ9+6n+zSjhqQ/BHFq0ec/AydZlzek+Q0ZliD qetV15zb/MHxOA7vzQqNvZLPf4M9tH6wRsKQrrQa6Iz3oVYk3jK7czSw89vgK/gD6UoA +8eaKsYGsh6E16ohvT4sEbd8KnZIWhCjZgmYgPb1RtD7NVUCeETJUlVKJGuQrn/xuoQw UPZqXtDkXFA0+fywUMPo3LpL4yMdWXQ4Prhtp6snsc2pit5g9r0oifwMPmfauxVvmUZE 4ABw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=nvsEnZ076OwdPyi/GUAK85QsSX+9bAobn4d23nIRRzE=; b=oEvN/3VKADuA1bc9IxjQ3hXOE972Vysta4KwPfC7ltHs3p+ZZxouo/+1mOywDBpbtU dQ6flfVDGp8tZPOcx1Dz51zpjbtSND+JPIb6Gz7puusW1aogKED+AwzEvQAd7bjYNUKY q9ChgrnyU+vp1g9a2HYyfWKiwg9zLmMIgiqr10ajkyP2FBljPi+GKCoGXMk3F7NF+nUc LceUrnyCbz6aW4ll7ecMX4ZTPAgQMn5OZd04xc7urrdRLucQK6DU94h+pJUKb3MlJVeU e9VcVMtvrvawz9iBgWOmvyzBvjwp53XTO/9QsPUt2d/dymp4DiBnO4Ov1j9PjmToU59M pJFw== X-Gm-Message-State: AOAM533/TL7Iy78IivqxRtaqsn5WdXf3h32cr68Dk0UNG4SZUmzz3lxY y+UveHlQymaUVGbQx/HoUMQqfFIw/6Lsc2u0dTo= X-Google-Smtp-Source: ABdhPJxRZyUXlLXgLtAuQl85lf/FHEHC4O+wfJuUZjGzznyry5y6QjNeOEuwBVh3X2U+6MXciwUaewTXJax24enaz1I= X-Received: by 2002:a9d:20c1:: with SMTP id x59mr1959996ota.36.1598702516120; Sat, 29 Aug 2020 05:01:56 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Philipp Stephani Date: Sat, 29 Aug 2020 14:01:45 +0200 Message-ID: Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally To: Pip Cet Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.3 (/) X-Debbugs-Envelope-To: 43100 Cc: 43100@debbugs.gnu.org, Stefan Monnier X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.7 (/) Am Sa., 29. Aug. 2020 um 11:42 Uhr schrieb Pip Cet : > > I'm having trouble with pcase's behavior. > > (pcase "a" > ((or (pred symbolp) name) > (let ((foo 'bar)) name))) > > throws an error. It shouldn't. Isn't this case documented in the manual? The last section of https://www.gnu.org/software/emacs/manual/html_node/elisp/pcase-Macro.html states: "It makes no sense for each sub-pattern [in an `or' sequence] to let-bind a different set of symbols because the body forms have no way to distinguish which sub-pattern matched and choose among the different sets." From debbugs-submit-bounces@debbugs.gnu.org Sat Aug 29 10:28:36 2020 Received: (at 43100) by debbugs.gnu.org; 29 Aug 2020 14:28:36 +0000 Received: from localhost ([127.0.0.1]:48830 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kC1qN-00012C-Lc for submit@debbugs.gnu.org; Sat, 29 Aug 2020 10:28:36 -0400 Received: from mail-oi1-f175.google.com ([209.85.167.175]:46197) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kC1qL-00011z-Sw for 43100@debbugs.gnu.org; Sat, 29 Aug 2020 10:28:34 -0400 Received: by mail-oi1-f175.google.com with SMTP id v13so3247707oiv.13 for <43100@debbugs.gnu.org>; Sat, 29 Aug 2020 07:28:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=6u8FltFOkxdmCm/81vkgwSZ7zo0QrqGTmTZfDtrkVzc=; b=EaEzAWt6vXk5C8WNXSnOW8+6zCkgiA8ZVCaEBl0qRzEZshenpdiJnr5m6F6yTLZ6If 6y52TeTXGJfCHZrjU0zy49IUNl7zPnwOjrxR8gF5Ejee04cYm0re+oH1GyLIxm+a1V93 Wm+q/7D6z8Q2D4dES8UmV67VbwjXvrp9wmKOUZIy2K9WDohIi8dF4QdG1JrjDUmXzPZl cR90sygtHMqmW2V7SBjKk2DParhofKcbsxe5AQlkMB4+Au4EAWv/Ej9EBuGWquiuuKVr frQsK16JXJQyx5KNluUH4oWMo2unxkXC9umNTs/edsoZ9LnKUkr76bO4PBgqY+n/3Svv +qeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=6u8FltFOkxdmCm/81vkgwSZ7zo0QrqGTmTZfDtrkVzc=; b=Z2i4Cvi197vcj9mznrlXpzMj70FbeBh3Yi6SQVjZbuGytLyrzhw6bVcXO+GJvMUMQj yqvUhggpVByNja9oI34O0VgmVrUk1l0BNZdcPOJxNBBF+jcwW6nMA1ZcfbvG1KZizGcf fqOZYaeczgxN3aF+Hjk5TEwD6jymwwNk2T8+p3oD6xm3JdPWkgGzJdsRs6F+aVNiYtU8 kwZEkDEpfrtagXbZVxIdObhAaVBnPXIhgYaoLd5hA+mJtjf2siIE0KHFGWyMOpIVK0RB 8/UBfbcNPNchOIwj1q7tnhFVzJvpuat+gUlzHl6k/hW51FUWUVcPbi4lNa2BFSL4BQJg uVEg== X-Gm-Message-State: AOAM531uGhQrdbvtUNcd9a0ztTxsmYueHkfl0WykAE+obMR7VVfyi1+d KVVQthMJwJcd1RcLMh3PqaZoRVH7utRtd76Pcxk= X-Google-Smtp-Source: ABdhPJw4wppa/HTFsU8ADOALrsLDgFhdCowER/WGfbJfX31TNpVOr2I3lotdlR5ZrwLsrJezSaZEReVdOjwqHvXHEFM= X-Received: by 2002:aca:dc04:: with SMTP id t4mr2060951oig.30.1598711308071; Sat, 29 Aug 2020 07:28:28 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Pip Cet Date: Sat, 29 Aug 2020 14:27:51 +0000 Message-ID: Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally To: Philipp Stephani Content-Type: multipart/mixed; boundary="0000000000009dd90c05ae04fb9c" X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 43100 Cc: 43100@debbugs.gnu.org, Stefan Monnier X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --0000000000009dd90c05ae04fb9c Content-Type: text/plain; charset="UTF-8" On Sat, Aug 29, 2020 at 12:01 PM Philipp Stephani wrote: > Am Sa., 29. Aug. 2020 um 11:42 Uhr schrieb Pip Cet : > > I'm having trouble with pcase's behavior. > > > > (pcase "a" > > ((or (pred symbolp) name) > > (let ((foo 'bar)) name))) > > > > throws an error. It shouldn't. > > Isn't this case documented in the manual? The last section of > https://www.gnu.org/software/emacs/manual/html_node/elisp/pcase-Macro.html > states: > "It makes no sense for each sub-pattern [in an `or' sequence] to > let-bind a different set of symbols because the body forms have no way > to distinguish which sub-pattern matched and choose among the > different sets." Thanks for pointing this out. I disagree with what the documentation says there: it does make perfect sense, to me, to conditionally shadow a (lexical) let binding with a pcase-let one, and body forms will have no trouble in practice distinguishing between the outer and the inner let-binding. The code obviously attempts to handle this case, too, it just doesn't get it perfectly right. I agree and accept that pcase is very limited, and it probably always will be, but I think those limitations shouldn't be entirely arbitrary, and hitting them shouldn't cause silently malfunctioning code but error messages. Things like the behavior of (pcase-let ((`(,a ,@b) (list 3 4))) a) just seem puzzling to me. There are good reasons not to implement sublist matching (though I don't think those reasons are sufficient not to have a simple implementation anyway), so an error message would be acceptable, but the current implementation treats \,@ as an ordinary symbol, which doesn't help anyone. Sorry for complaining. Here's a patch. --0000000000009dd90c05ae04fb9c Content-Type: text/x-patch; charset="US-ASCII"; name="0001-Complain-about-in-backquote-pcase-patterns.patch" Content-Disposition: attachment; filename="0001-Complain-about-in-backquote-pcase-patterns.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_kefr9tay0 RnJvbSBjNTI3MDhkOTJkZWM0YTZkNzgxMGQ2MzRkZDRmZjIzYTJjYmNhMWVjIE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiBQaXAgQ2V0IDxwaXBjZXRAZ21haWwuY29tPgpEYXRlOiBTYXQs IDI5IEF1ZyAyMDIwIDE0OjIxOjI5ICswMDAwClN1YmplY3Q6IFtQQVRDSF0gQ29tcGxhaW4gYWJv dXQgLEAgaW4gYmFja3F1b3RlIHBjYXNlIHBhdHRlcm5zCgoqIGxpc3AvZW1hY3MtbGlzcC9wY2Fz ZS5lbCAoXGApOiBDb21wbGFpbiB1cG9uIGVuY291bnRlcmluZyBcLEAgaW4KYmFja3F1b3RlIHBj YXNlIHBhdHRlcm5zLgotLS0KIGxpc3AvZW1hY3MtbGlzcC9wY2FzZS5lbCB8IDEgKwogMSBmaWxl IGNoYW5nZWQsIDEgaW5zZXJ0aW9uKCspCgpkaWZmIC0tZ2l0IGEvbGlzcC9lbWFjcy1saXNwL3Bj YXNlLmVsIGIvbGlzcC9lbWFjcy1saXNwL3BjYXNlLmVsCmluZGV4IGE4Y2UyMzI4NGMuLjY0MmZm MGY3M2EgMTAwNjQ0Ci0tLSBhL2xpc3AvZW1hY3MtbGlzcC9wY2FzZS5lbAorKysgYi9saXNwL2Vt YWNzLWxpc3AvcGNhc2UuZWwKQEAgLTk3MSw2ICs5NzEsNyBAQCBcYAogICAoZGVjbGFyZSAoZGVi dWcgKHBjYXNlLVFQQVQpKSkKICAgKGNvbmQKICAgICgoZXEgKGNhci1zYWZlIHFwYXQpICdcLCkg KGNhZHIgcXBhdCkpCisgICAoKGVxIChjYXItc2FmZSBxcGF0KSAnXCxAKSAoZXJyb3IgInN1Ymxp c3QgbWF0Y2hpbmcgbm90IHN1cHBvcnRlZCIpKQogICAgKCh2ZWN0b3JwIHFwYXQpCiAgICAgYChh bmQgKHByZWQgdmVjdG9ycCkKICAgICAgICAgICAoYXBwIGxlbmd0aCAsKGxlbmd0aCBxcGF0KSkK LS0gCjIuMjguMAoK --0000000000009dd90c05ae04fb9c-- From debbugs-submit-bounces@debbugs.gnu.org Sat Aug 29 12:06:26 2020 Received: (at 43100) by debbugs.gnu.org; 29 Aug 2020 16:06:26 +0000 Received: from localhost ([127.0.0.1]:48930 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kC3N3-0003Qz-SQ for submit@debbugs.gnu.org; Sat, 29 Aug 2020 12:06:26 -0400 Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:1054) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kC3N1-0003Qm-GV for 43100@debbugs.gnu.org; Sat, 29 Aug 2020 12:06:24 -0400 Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 902B5809C0; Sat, 29 Aug 2020 12:06:17 -0400 (EDT) Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id D8C788073F; Sat, 29 Aug 2020 12:06:15 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1598717175; bh=xgMP1NHOZG3DzJnMJY76YQsY+HSFbm1Uo+jTnoJCN6Q=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From; b=o0phF5oC+k14y8i9f3DN3fsXdZvfo3iDDvNO7jMaahPklFwtV16GNIFjs711gCoTf 2j/y9ZP6W19xJ7kE2iPZDwakHlDZteyzKqMG2xcUgDwmT2NmUQgNAgJ8o2Fi7oIHfS 7g2koxQoWz6agns+YDxA2kTvirr/dGod5qo8BVye/sIpMRSbc+ShUJaDp8PluMQJ3x cflbpnpQCfbA8yCpeNKcoVtTya0VWFQg9VNfh1qZClP7aC8B5LsvL3o17PPozpdSyF WCQhXIs9TOUAivEaGnS2/BLvSn5p72w8wAxNaLckoA6JkCqyTSxhCwJKo0BY+dsEL3 B7K98U5nYt3Qw== Received: from alfajor (unknown [45.72.232.131]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 9EA1F120314; Sat, 29 Aug 2020 12:06:15 -0400 (EDT) From: Stefan Monnier To: Pip Cet Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally Message-ID: References: Date: Sat, 29 Aug 2020 12:06:15 -0400 In-Reply-To: (Pip Cet's message of "Sat, 29 Aug 2020 14:27:51 +0000") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-SPAM-INFO: Spam detection results: 0 ALL_TRUSTED -1 Passed through trusted hosts only via SMTP AWL -0.061 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain KAM_SHORT 0.001 Use of a URL Shortener for very short URL X-SPAM-LEVEL: X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 43100 Cc: Philipp Stephani , 43100@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) >> > I'm having trouble with pcase's behavior. >> > >> > (pcase "a" >> > ((or (pred symbolp) name) >> > (let ((foo 'bar)) name))) >> > >> > throws an error. It shouldn't. >> >> Isn't this case documented in the manual? The last section of >> https://www.gnu.org/software/emacs/manual/html_node/elisp/pcase-Macro.html >> states: >> "It makes no sense for each sub-pattern [in an `or' sequence] to >> let-bind a different set of symbols because the body forms have no way >> to distinguish which sub-pattern matched and choose among the >> different sets." > > Thanks for pointing this out. > > I disagree with what the documentation says there: it does make > perfect sense, to me, to conditionally shadow a (lexical) let binding > with a pcase-let one, and body forms will have no trouble in practice > distinguishing between the outer and the inner let-binding. How do you expect them to distinguish? IIUC you want (pcase V ((or (pred symbolp) name) (let ((foo 'bar)) name))) to behave like (cond ((symbolp V) (let ((foo 'bar)) name)) (t (let ((name V)) (let ((foo 'bar)) name)))) ? I'd rather not go there since it means that the single occurrence of the `name` identifier in the branch's body refers to two different variable bindings depending on which pattern was matched. It smells of dynamic scoping, tho it is admittedly compatible with lexical-scoping but only at the cost of having to duplicate the branch's body. The "intended" behavior instead would be to behave like (cond ((symbolp V) (let ((name nil)) (let ((foo 'bar)) name))) (t (let ((name V)) (let ((foo 'bar)) name)))) That's already the behavior you get if you switch the two: (macroexpand '(pcase V ((or (and (pred foo) name) (pred symbolp)) (let ((foo 'bar)) name)))) => (let* ((pcase-0 (lambda (name) (let ((foo 'bar)) name)))) (cond ((foo V) (funcall pcase-0 V)) ((symbolp V) (funcall pcase-0 nil)) (t nil))) the fact that the behavior depends on the order of elements in `or` is an undesirable side effect of the implementation technique. > Things like the behavior of > > (pcase-let ((`(,a ,@b) (list 3 4))) > a) > > just seem puzzling to me. There are good reasons not to implement > sublist matching (though I don't think those reasons are sufficient > not to have a simple implementation anyway), I don't know of a simple implementation. > so an error message would be acceptable, You're probably right. > Sorry for complaining. Here's a patch. LGTM, Stefan From debbugs-submit-bounces@debbugs.gnu.org Sun Aug 30 12:22:26 2020 Received: (at 43100) by debbugs.gnu.org; 30 Aug 2020 16:22:26 +0000 Received: from localhost ([127.0.0.1]:50649 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCQ66-00074G-Dh for submit@debbugs.gnu.org; Sun, 30 Aug 2020 12:22:26 -0400 Received: from mail-oo1-f43.google.com ([209.85.161.43]:35447) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCQ64-000743-OX for 43100@debbugs.gnu.org; Sun, 30 Aug 2020 12:22:25 -0400 Received: by mail-oo1-f43.google.com with SMTP id k13so548235oor.2 for <43100@debbugs.gnu.org>; Sun, 30 Aug 2020 09:22:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=w07nNXECaXWljAI84FYLJ8MZMakE00ftqm/8EmghEng=; b=Iu6h+3p8lYul7D1cYx7XnEb5vRxiXxQ6TNFAF3tzf/IQetE2nMgE+CUQ8Fm1wKTd27 zWxFIa/uJrU5ZcqMVqhWpZ2jQlQthuR0xULBHJ1A7YlwKvRMa/f1cbTXFtq6phmrRZUJ IOddHO9Lk57EGB01mJKQV6+dZFVOlbFVne5FQ60OJTRW76syrxTHE2OpgifFvE2ma96l Ciku9bSkuA3w5GmXbcxh1y0a0Uv8dNH6FMi17xsJVo9tIZ/VW/vLdjFiZTpBtuF1tCWE bsdz888irjxAOSWWkQR7uuNqZ23ZAHQIzn8HLnqwysIOCAObIe+v9HPyo7ujPSvgqsBZ ZyUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=w07nNXECaXWljAI84FYLJ8MZMakE00ftqm/8EmghEng=; b=tVgjHouIwGpFi3L72EmQlvNLAjh5Xe45MR+yMjWxgBn3Zkd2oONYcYgLxoDCR3Z3Np 6LulY4hGnCjAnWEKGZjdLx0uJfJp6CsEQ2VVvY38H9ci2NUh0uBuTVT/IASf7QOKFuL0 hV/IztF+65jFchF4KN6u2/UWYmRbsXoyuldsxMRzL9mkids5RCfitb3XY/CqTl3ItfOn Y5qV6aKo4BQwsgVODxWuZa35swI4uE2Lhxw2vn8RS7j3mKu+8EuGkQNprkcStKXv//pB 3ftEEDxbjjQj+ytv0HPv8DEIwJb+ZaLkBCS2J5rjzSeSyClZScgWWqAjLEy3lZRPnUtQ rkEg== X-Gm-Message-State: AOAM531m7QnJUSFsY9qRMcbCA4pdGGaJW+JyhDactCCEBebOcASbxg/X Zd2QhMiVVsR1R5qyrIFXRvIFqejKj/hJgf0GEDs= X-Google-Smtp-Source: ABdhPJwzK9Q2Cc9qXRCviwjmV7Ht+7MSjinKq9nTotNWCdAXztHg//ui0DCCdl2yuKeFiESu9avmot02mOjGSlPSWx0= X-Received: by 2002:a4a:aa42:: with SMTP id y2mr5315735oom.88.1598804538893; Sun, 30 Aug 2020 09:22:18 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Pip Cet Date: Sun, 30 Aug 2020 16:21:42 +0000 Message-ID: Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally To: Stefan Monnier Content-Type: text/plain; charset="UTF-8" X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 43100 Cc: Philipp Stephani , 43100@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On Sat, Aug 29, 2020 at 4:06 PM Stefan Monnier wrote: > >> > I'm having trouble with pcase's behavior. > >> > > >> > (pcase "a" > >> > ((or (pred symbolp) name) > >> > (let ((foo 'bar)) name))) > >> > > >> > throws an error. It shouldn't. > >> > >> Isn't this case documented in the manual? The last section of > >> https://www.gnu.org/software/emacs/manual/html_node/elisp/pcase-Macro.html > >> states: > >> "It makes no sense for each sub-pattern [in an `or' sequence] to > >> let-bind a different set of symbols because the body forms have no way > >> to distinguish which sub-pattern matched and choose among the > >> different sets." > > > > Thanks for pointing this out. > > > > I disagree with what the documentation says there: it does make > > perfect sense, to me, to conditionally shadow a (lexical) let binding > > with a pcase-let one, and body forms will have no trouble in practice > > distinguishing between the outer and the inner let-binding. > > How do you expect them to distinguish? By repeating the pcase pattern's predicate, usually, or by relying on other knowledge about the previous value. That's in practice, in theory you can use gensym or an inaccessible cons. > IIUC you want > > (pcase V > ((or (pred symbolp) name) > (let ((foo 'bar)) name))) > > to behave like > > (cond > ((symbolp V) (let ((foo 'bar)) name)) > (t (let ((name V)) (let ((foo 'bar)) name)))) > > ? Yes, that's correct. It's also how (pcase V ((or (pred symbolp) name) name) behaves... > I'd rather not go there You'd rather have the behavior of (pcase V ((or pred symbolp) name) EXPR) depend on the complexity of EXPR? > since it means that the single occurrence of the > `name` identifier in the branch's body refers to two different variable > bindings depending on which pattern was matched. It smells of dynamic > scoping, tho it is admittedly compatible with lexical-scoping but only at > the cost of having to duplicate the branch's body. Well, I'm afraid pcase does smell of dynamic scoping :-) More precisely, to me, what pcase simulates is building a lexical environment, then evaluating the BODY argument with the environment as second argument. (pcase EXP (PAT BODY)) is very roughly: (for-each-possible-environment ENV (if (equalish (eval PAT ENV) EXP) (return (eval BODY ENV))) where for-each-possible-environment magically finds the smallest (or "best") ENV first. I think it would be nice to have a lexical three-argument version of pcase which specifies which variables are output values, treating the remaining ones as input values, to make it easier to build non-constant patterns. But that would be very different from what pcase does do today, which is closer to what I hinted at above. IOW, if you want to call a function with arguments determined by pcase-like patterns, why not introduce pcase-call so something like the following would work: (defun f (hello world) (cons hello world)) (let ((space " ") (hw "hello world")) (pcase-call 'f ((concat hello space world) hw))) (that would introduce named function arguments, which I think would be a nice bonus)? But it's not what pcase is! There's no function call or argument list in there, just expressions involved in environments. As for duplicating the body, that is an implementation detail. You can easily avoid it by producing (let ((name name)) (cond ((symbolp V) X) (progn (setq name V) X))) disallowing the modification of name in X. > The "intended" behavior instead would be to behave like > > (cond > ((symbolp V) (let ((name nil)) (let ((foo 'bar)) name))) > (t (let ((name V)) (let ((foo 'bar)) name)))) > > That's already the behavior you get if you switch the two: > > (macroexpand '(pcase V > ((or (and (pred foo) name) (pred symbolp)) > (let ((foo 'bar)) name)))) > => > (let* ((pcase-0 (lambda (name) (let ((foo 'bar)) name)))) > (cond ((foo V) (funcall pcase-0 V)) > ((symbolp V) (funcall pcase-0 nil)) > (t nil))) I don't see where the nil comes from, or why it's a useful choice for a default value. > the fact that the behavior depends on the order of elements in `or` is > an undesirable side effect of the implementation technique. It also depends on the complexity of the branch. It seems to me there are at least three consistent ways of behaving (throw an error, bind name to nil, bind name to name), with an inconsistent fourth way being what's currently implemented. > > Things like the behavior of > > > > (pcase-let ((`(,a ,@b) (list 3 4))) > > a) > > > > just seem puzzling to me. There are good reasons not to implement > > sublist matching (though I don't think those reasons are sufficient > > not to have a simple implementation anyway), > > I don't know of a simple implementation. Here's my better-than-nothing attempt. I don't think that's complex; if anything, it's too trivial. (pcase-defmacro append (&rest patterns) (if patterns (let* ((r1 (gensym)) (r2 (gensym)) (pat (list '\` (cons (list '\, (list 'and r1 (car patterns))) (list '\, (list 'and r2 (cons 'append (cdr patterns))))))) (f (eval `(lambda (l) (catch 'pcase--append (dotimes (i (1+ (length l))) (let ((l1 (seq-subseq l 0 i)) (l2 (seq-subseq l i))) (pcase (cons l1 l2) (,pat (throw 'pcase--append (cons ,r1 ,r2)))))))) t))) `(app ,f ,pat)) ''nil)) > > > so an error message would be acceptable, > > You're probably right. > > > Sorry for complaining. Here's a patch. > > LGTM, > > > Stefan > From debbugs-submit-bounces@debbugs.gnu.org Sun Aug 30 14:07:59 2020 Received: (at 43100) by debbugs.gnu.org; 30 Aug 2020 18:07:59 +0000 Received: from localhost ([127.0.0.1]:50712 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCRkF-000131-FM for submit@debbugs.gnu.org; Sun, 30 Aug 2020 14:07:59 -0400 Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:52442) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCRkD-00012m-2v for 43100@debbugs.gnu.org; Sun, 30 Aug 2020 14:07:58 -0400 Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 0EE8080B69; Sun, 30 Aug 2020 14:07:51 -0400 (EDT) Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id D69498066B; Sun, 30 Aug 2020 14:07:48 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1598810868; bh=dVo02K/GJSZKK0+eG6fgaUVb47Yhg/ndzsvRMUils0I=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From; b=cemW9EOLMRQ8a54JT8aMV0UgvhUgOD3pJnHthJopMqoTL5bz/YRHQm5UszRfoxvou jZukgbvQ6CgXd/lQiuRm6c7Vrq9xNgnFq71a/1+Q0Go75omat2mMoEFvChmURPul0A lIrLWw0ljsUQ/cTfHuKQr2pDlnGVmd/mJMEFTe8v88oTv1r9QQgw2JJMoXwtGg+vS3 IaorihiIdKmQT1U0uRv7cK+uB3I5E9r5wWw4akqcAO24MME5u9Yi1a5b/g550sZd4j P+VfnBhJlwFl0pPdAqM+xJBgNDqojE0aK5UUZaIXJlWaL0ge58eYHEAyvHWLDySfRE O40OW2LWtX+kg== Received: from alfajor (unknown [45.72.232.131]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id A3BF4120535; Sun, 30 Aug 2020 14:07:48 -0400 (EDT) From: Stefan Monnier To: Pip Cet Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally Message-ID: References: Date: Sun, 30 Aug 2020 14:07:47 -0400 In-Reply-To: (Pip Cet's message of "Sun, 30 Aug 2020 16:21:42 +0000") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-SPAM-INFO: Spam detection results: 0 ALL_TRUSTED -1 Passed through trusted hosts only via SMTP AWL -0.060 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain X-SPAM-LEVEL: X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 43100 Cc: Philipp Stephani , 43100@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) >> IIUC you want >> >> (pcase V >> ((or (pred symbolp) name) >> (let ((foo 'bar)) name))) >> >> to behave like >> >> (cond >> ((symbolp V) (let ((foo 'bar)) name)) >> (t (let ((name V)) (let ((foo 'bar)) name)))) >> >> ? > > Yes, that's correct. It's also how (pcase V ((or (pred symbolp) name) > name) behaves... Indeed, but that's an accident. Ideally it should either signal an error at macro-expansion time, or return nil when V is a symbol. Since the current implementation doesn't go to the effort of doing either of those, we instead limit ourselves to recommend against using such patterns (IOW, "use at your own risks"). >> I'd rather not go there > You'd rather have the behavior of (pcase V ((or pred symbolp) name) > EXPR) depend on the complexity of EXPR? More specifically, I'd rather not choose a semantics that imposes duplicating the branch body, since we have no control over its size and that can hence lead to potential code size explosion. A code size explosion due to a particular implementation choice is undesirable, but a code size explosion imposed by the semantics is much more problematic. > I think it would be nice to have a lexical three-argument version of > pcase which specifies which variables are output values, treating the > remaining ones as input values, to make it easier to build > non-constant patterns. The design of `pcase` assumes you want to optimize away the tests that are common to the various patterns. That can't be done with dynamic patterns. > IOW, if you want to call a function with arguments determined by > pcase-like patterns, why not introduce pcase-call so something like > the following would work: > > (defun f (hello world) (cons hello world)) > > (let ((space " ") (hw "hello world")) > (pcase-call 'f ((concat hello space world) hw))) How do you intend to implement this? > As for duplicating the body, that is an implementation detail. You can > easily avoid it by producing > > (let ((name name)) > (cond ((symbolp V) X) > (progn (setq name V) X))) So it's more like my option of returning nil, except it would return the value of a surrounding `name` variable? That could be done, but I'm not convinced it'd be more often useful. > disallowing the modification of name in X. That's rather hard to do (and I don't see what would be the benefit here). >> The "intended" behavior instead would be to behave like >> >> (cond >> ((symbolp V) (let ((name nil)) (let ((foo 'bar)) name))) >> (t (let ((name V)) (let ((foo 'bar)) name)))) >> >> That's already the behavior you get if you switch the two: >> >> (macroexpand '(pcase V >> ((or (and (pred foo) name) (pred symbolp)) >> (let ((foo 'bar)) name)))) >> => >> (let* ((pcase-0 (lambda (name) (let ((foo 'bar)) name)))) >> (cond ((foo V) (funcall pcase-0 V)) >> ((symbolp V) (funcall pcase-0 nil)) >> (t nil))) > > I don't see where the nil comes from, or why it's a useful choice for > a default value. It comes from the absence of a binding for `name` and was chosen because nil is the standard default value in Elisp. It comes from this code in pcase.el: (let ((args (mapcar (lambda (pa) (let ((v (assq (car pa) vars))) (setq vars (delq v vars)) (cdr v))) prevvars))) ;; If some of `vars' were not found in `prevvars', that's ;; OK it just means those vars aren't present in all ;; branches, so they can be used within the pattern ;; (e.g. by a `guard/let/pred') but not in the branch. ;; FIXME: But if some of `prevvars' are not in `vars' we ;; should remove them from `prevvars'! `(funcall ,res ,@args))))))) The computation of `args` searches in `vars` for the bindings expected by the branch (stored in `prevvars` the first time we encountered that branch). The assq+cdr will return nil if a var from `prevvars` isn't found in `vars`. >> the fact that the behavior depends on the order of elements in `or` is >> an undesirable side effect of the implementation technique. > It also depends on the complexity of the branch. > It seems to me there are at least three consistent ways of behaving > (throw an error, bind name to nil, bind name to name), with an > inconsistent fourth way being what's currently implemented. The current implementation amounts to "we should signal an error but we don't bother doing so and just warn against it in the manual". Patch welcome ;-) >> I don't know of a simple implementation. > Here's my better-than-nothing attempt. I don't think that's complex; > if anything, it's too trivial. So you give it a search-based semantics. The problem with it for me is that if we turn `(,a ,@b) into (append `(,a) b) the pcase match will take a lot more time than the equivalent `(,a . ,b) Of course, you can try and handle these "easy" cases more efficiently, but then your ,@ will sometimes be very cheap and sometimes very expensive (depending on when an optimization can be applied), which I think is a misfeature (it's for this same reason that I dislike CL keyword arguments for functions). I think it's fine to have such a search-based `append` (because it's "reliably expensive") but I'd rather not automatically use it for ,@ [ BTW, you don't need (nor want) `eval` in your definition. ] Stefan From debbugs-submit-bounces@debbugs.gnu.org Mon Aug 31 15:33:30 2020 Received: (at 43100) by debbugs.gnu.org; 31 Aug 2020 19:33:30 +0000 Received: from localhost ([127.0.0.1]:53738 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCpYX-0001EU-LU for submit@debbugs.gnu.org; Mon, 31 Aug 2020 15:33:30 -0400 Received: from mail-ot1-f46.google.com ([209.85.210.46]:43934) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCpYU-0001EF-Jd for 43100@debbugs.gnu.org; Mon, 31 Aug 2020 15:33:28 -0400 Received: by mail-ot1-f46.google.com with SMTP id v16so6361976otp.10 for <43100@debbugs.gnu.org>; Mon, 31 Aug 2020 12:33:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=OOxEnggrg5w3krgjf2IcUnPALzRdHZ7/QVxHdTs8oS4=; b=HW51mbI/rMzKIGOrH6U1DPhPkGTZarXoBAC9sPowHWxAPz/AP1nburmrr/59axW05J zuC8EbzK37jfAv8L5RS4cdQqUMd7o3l5nGSDxBmZyNgts6DVAPG18GXKQCjU0Y5Jqlcj yaLtXA1xeZGhmNW1JCjpORryZbbaXZfEc2foiNzTr2HWepPd7k33FU7FWxzJiA3HSBDK j0Au8vJuBxkOKkeW7VstWqkX0IV2WwxKQ54Oc70O4JcZEZQ81WCmGqRTLhzO2qSdRKml ipbjWJUoGPBibjMDYDuHt2FbeC0A/zgfs/TK5V4g5u1PwH5S58DdClHSZ/3NLzc3MZ5t BMhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=OOxEnggrg5w3krgjf2IcUnPALzRdHZ7/QVxHdTs8oS4=; b=GWP7CuQMunbtVySsjD3tykasfhlEf0a5jqowyAGC3bd2tpq+eYkAt10+wcaIR/khgS L9OFOOPE9blNxCbvOUEVZmJnfB//PoiEJGLSOsCeBNGxjJFDDuIgS0gTTLcZDwcWptaQ yCCTWgUfrolaSje7lS4MJwi+79n+++WirJx681CpRbmG7t2phlCmDqMuN3k3SL8N1BqE GcNrd7Z3rdUZkaoYNUhuZbglgqqRrBNBeJjDVfxwnogLXMlxgRxFIJ7oYr5J/QcyDFLq K1u1LSKtCwqcRcw6CNGwj6oDB8lRF360xOHKXUc28p4Ac2sAFtjf1F7XyT5+SvmMYVKb yGBA== X-Gm-Message-State: AOAM531wEVgHfhZQaawblX2IRrOyVdAIZ9ZUU+o6ScN4AuvroQxsUPUZ LzFQtnfqGt+89TCWsVfONiBs0bNYf9NZisYaZ4g= X-Google-Smtp-Source: ABdhPJyFESWBl+QKFzmW/Pa5ZS+lcPw6YE3T9SMslk3E2mBL6KF7RhPc6Vtj9d9t3fh3ylser0xygCszTr+p/XmSSr8= X-Received: by 2002:a9d:6d92:: with SMTP id x18mr1981049otp.287.1598902400698; Mon, 31 Aug 2020 12:33:20 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Pip Cet Date: Mon, 31 Aug 2020 19:32:43 +0000 Message-ID: Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally To: Stefan Monnier Content-Type: multipart/mixed; boundary="0000000000009fed8e05ae317999" X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 43100 Cc: Philipp Stephani , 43100@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --0000000000009fed8e05ae317999 Content-Type: text/plain; charset="UTF-8" Hello Stefan, On Sun, Aug 30, 2020 at 6:07 PM Stefan Monnier wrote: > > >> IIUC you want > >> > >> (pcase V > >> ((or (pred symbolp) name) > >> (let ((foo 'bar)) name))) > >> > >> to behave like > >> > >> (cond > >> ((symbolp V) (let ((foo 'bar)) name)) > >> (t (let ((name V)) (let ((foo 'bar)) name)))) > >> > >> ? > > > > Yes, that's correct. It's also how (pcase V ((or (pred symbolp) name) > > name) behaves... > > Indeed, but that's an accident. Ideally it should either signal an > error at macro-expansion time, or return nil when V is a symbol. So, as I half-expected, the reaction to "pcase isn't powerful enough" is "let's make it less powerful" :-) Seriously, I get the impression you strongly feel pcase shouldn't be (more) powerful, it should instead make non-explicit but fairly strong complexity promises. I disagree: in practice, complexity promises and optimization based on them are often unnecessary. In fact, there's a Lisp tradition of using assq and memq rather than building ad-hoc hash tables, even though that often means run time is theoretically O(n^2) rather than O(n log(n)). > Since the current implementation doesn't go to the effort of doing > either of those, we instead limit ourselves to recommend against using > such patterns (IOW, "use at your own risks"). > >> I'd rather not go there > > You'd rather have the behavior of (pcase V ((or pred symbolp) name) > > EXPR) depend on the complexity of EXPR? > > More specifically, I'd rather not choose a semantics that imposes > duplicating the branch body, since we have no control over its size and > that can hence lead to potential code size explosion. You're right, and it's a good thing that the duplication of the branch body is a fixable implementation detail rather than something imposed by the semantics. > A code size explosion due to a particular implementation choice is > undesirable, but a code size explosion imposed by the semantics is much > more problematic. Again, I don't think that's the case here. > > I think it would be nice to have a lexical three-argument version of > > pcase which specifies which variables are output values, treating the > > remaining ones as input values, to make it easier to build > > non-constant patterns. > > The design of `pcase` assumes you want to optimize away the tests that > are common to the various patterns. That can't be done with dynamic > patterns. Or it's a bit more difficult, at least... > > IOW, if you want to call a function with arguments determined by > > pcase-like patterns, why not introduce pcase-call so something like > > the following would work: > > > > (defun f (hello world) (cons hello world)) > > > > (let ((space " ") (hw "hello world")) > > (pcase-call 'f ((concat hello space world) hw))) > > How do you intend to implement this? Proof-of-concept attached; I'm no longer sure I want to be able to say (concat hello space world) rather than (concat hello (pred (equal space)) world); it's inconsistent to use `equal' here rather than `eq' for ordinary symbols (can't we at least use `eql'?), and I'm too worried about adding an optional argument called `space' and changing the interpretation of pcase-calls far away. The difficult part, in fact, is deciding that we want the arglist to be part of the exposed function API: given an "arglist" function, the rest of the implementation seems unproblematic, though some workarounds for lexical binding are required (if nothing else, this is an interesting exercise in how painful lexical binding can be to work with). > > As for duplicating the body, that is an implementation detail. You can > > easily avoid it by producing > > > > (let ((name name)) > > (cond ((symbolp V) X) > > (progn (setq name V) X))) > > So it's more like my option of returning nil, except it would return > the value of a surrounding `name` variable? That could be done, but I'm > not convinced it'd be more often useful. I started out with a fairly explicit practical problem: parsing GCC machine descriptions, which are (essentially) sexps but have made the mistake of having "optional" non-final parts, and I think it would be great to express that in a pcase pattern, both for the obvious reasons of legibility and for some non-obvious reasons of my own. > > disallowing the modification of name in X. > > That's rather hard to do (and I don't see what would be the benefit here). I meant adding a cautionary note about it in the documentation, not actively preventing it. If we had read-only bindings, pcase would probably use them, but we don't. > >> The "intended" behavior instead would be to behave like > >> > >> (cond > >> ((symbolp V) (let ((name nil)) (let ((foo 'bar)) name))) > >> (t (let ((name V)) (let ((foo 'bar)) name)))) > >> > >> That's already the behavior you get if you switch the two: > >> > >> (macroexpand '(pcase V > >> ((or (and (pred foo) name) (pred symbolp)) > >> (let ((foo 'bar)) name)))) > >> => > >> (let* ((pcase-0 (lambda (name) (let ((foo 'bar)) name)))) > >> (cond ((foo V) (funcall pcase-0 V)) > >> ((symbolp V) (funcall pcase-0 nil)) > >> (t nil))) > > > > I don't see where the nil comes from, or why it's a useful choice for > > a default value. > > It comes from the absence of a binding for `name` and was chosen because > nil is the standard default value in Elisp. Sorry, I meant I don't see anything in the pcase input that justifies our using a nil value. > It comes from this code in pcase.el: > > (let ((args (mapcar (lambda (pa) > (let ((v (assq (car pa) vars))) > (setq vars (delq v vars)) > (cdr v))) > prevvars))) > ;; If some of `vars' were not found in `prevvars', that's > ;; OK it just means those vars aren't present in all > ;; branches, so they can be used within the pattern > ;; (e.g. by a `guard/let/pred') but not in the branch. > ;; FIXME: But if some of `prevvars' are not in `vars' we > ;; should remove them from `prevvars'! > `(funcall ,res ,@args))))))) > > The computation of `args` searches in `vars` for the bindings expected > by the branch (stored in `prevvars` the first time we encountered that > branch). The assq+cdr will return nil if a var from `prevvars` isn't > found in `vars`. Yes, it's the precise code I want to change. > >> the fact that the behavior depends on the order of elements in `or` is > >> an undesirable side effect of the implementation technique. > > It also depends on the complexity of the branch. > > It seems to me there are at least three consistent ways of behaving > > (throw an error, bind name to nil, bind name to name), with an > > inconsistent fourth way being what's currently implemented. > > The current implementation amounts to "we should signal an error but we > don't bother doing so and just warn against it in the manual". > Patch welcome ;-) You mean a patch that would make pcase less powerful by making what I want to do impossible rather than merely difficult? > >> I don't know of a simple implementation. > > Here's my better-than-nothing attempt. I don't think that's complex; > > if anything, it's too trivial. > > So you give it a search-based semantics. I don't think the semantics are at all unclear, except for the greedy vs shy question. The implementation could be very different, reasoning about the length of sequences matched by pcase subpatterns, of course. > The problem with it for me is that if we turn > > `(,a ,@b) > > into > > (append `(,a) b) List-final ,@ is too special, IMHO, to be turned into an (append) pattern at all. > the pcase match will take a lot more time than the equivalent > > `(,a . ,b) > > Of course, you can try and handle these "easy" cases more efficiently, > but then your ,@ will sometimes be very cheap and sometimes very > expensive (depending on when an optimization can be applied), which > I think is a misfeature (it's for this same reason that I dislike CL > keyword arguments for functions). I think it's an implementation detail. Some reasoning about the minimum and maximum length of sequences matched by pcase patterns could help ordinary pcases, too, though: (pcase '(a b c d) (`(,a ,b ,c ,d) (list a b c d))) could call (pcase--check-length EXPVAL 4 4) rather than calling consp four times, potentially descending into expensive predicates that are unnecessary. It's strange to read quotes that yo In general, of course, multiple ,@s in the same list will be slow because it's a difficult problem. > I think it's fine to have such a search-based `append` (because it's > "reliably expensive") but I'd rather not automatically use it for ,@ Again, I think that's a fundamental difference between us when it comes to the philosophy behind pcase. If I understand you correctly, you deliberately want to limit pcase, moving away from the intuitive definition of it that I gave above, because there might be a situation in which people expect better performance than our limited implementation can give them. Is that correct? I think that's a weak reason for a strong limitation, but of course those are subjective questions. For example, I don't expect (pcase 9 ((* x x) x)) to work, and the intuitive try-everything oracle would work for it. In any case, if there is such a fundamental difference of opinion, pcase simply isn't what I should be looking at. > [ BTW, you don't need (nor want) `eval` in your definition. ] Thank you! Premature "optimization"... Thanks again! --0000000000009fed8e05ae317999 Content-Type: text/x-emacs-lisp; charset="US-ASCII"; name="pcall.el" Content-Disposition: attachment; filename="pcall.el" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_keix5kit0 OzsgLSotIGxleGljYWwtYmluZGluZzogdDsgLSotCgooZGVmdW4gZiAoaGVsbG8gd29ybGQpCiAg KGNvbnMgaGVsbG8gd29ybGQpKQoKKGRlZnVuIHBjYWxsLWNvbGxlY3Qtc3ltYm9scy0xIChleHBy IHB1c2hlcikKICAoY29uZAogICAoKGNvbnNwIGV4cHIpCiAgICAocGNhbGwtY29sbGVjdC1zeW1i b2xzLTEgKGNhciBleHByKSBwdXNoZXIpCiAgICAocGNhbGwtY29sbGVjdC1zeW1ib2xzLTEgKGNk ciBleHByKSBwdXNoZXIpKQogICAoKHN5bWJvbHAgZXhwcikKICAgIChmdW5jYWxsIHB1c2hlciBl eHByKSkpKQoKKGRlZnVuIHBjYWxsLWNvbGxlY3Qtc3ltYm9scyAoYmluZGluZ3MpCiAgKGxldCAo bGlzdCkKICAgIChkb2xpc3QgKGJpbmRpbmcgYmluZGluZ3MpCiAgICAgIChwY2FsbC1jb2xsZWN0 LXN5bWJvbHMtMSBiaW5kaW5nCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobGFtYmRh ICh4KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAodW5sZXNzIChtZW1xIHggbGlz dCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocHVzaCB4IGxpc3QpKSkpKQog ICAgbGlzdCkpCgooZGVmdW4gcGNhbGwtbWFrZS1lbnZpcm9ubWVudCAoc3ltcykKICAobGV0IChl bnYpCiAgICAoZG9saXN0IChzeW0gc3ltcykKICAgICAgKHB1c2ggKGxpc3QgJ2NvbnMKICAgICAg ICAgICAgICAgICAgKGxpc3QgJ3F1b3RlIHN5bSkKICAgICAgICAgICAgICAgICAgYChjb25kaXRp b24tY2FzZSBlcnJvcgogICAgICAgICAgICAgICAgICAgICAgICxzeW0KICAgICAgICAgICAgICAg ICAgICAgKHZvaWQtdmFyaWFibGUgKHB1c2ggJyxzeW0gdW5ib3VuZC1zeW1zKSkpKQogICAgICAg ICAgICBlbnYpKQogICAgKGNvbnMgJ2xpc3QgKG5yZXZlcnNlIGVudikpKSkKCihkZWZ1biBwY2Fs bGVyIChmdW5jIHBhdHMpCiAgKGxldCogKChhcmdsaXN0IChhcmdsaXN0IGZ1bmMpKQogICAgICAg ICAoYXJnLXN5bWJvbHMgKHBjYWxsLWNvbGxlY3Qtc3ltYm9scyBhcmdsaXN0KSkpCiAgICBgKGxh bWJkYSAoZW52IHZhbHMpCiAgICAgICAoZG9saXN0IChzeW0gJyxhcmdsaXN0KQogICAgICAgICA7 OyAoaWYgKGFzc3Egc3ltIGVudikKICAgICAgICAgOzsgICAgICh3YXJuICJzaGFkb3dpbmcgdmFy aWFibGUgYmluZGluZyBmb3IgJVMiCiAgICAgICAgIDs7ICAgICAgICAgICBzeW0pKQogICAgICAg ICAoc2V0cSBlbnYgKGFzc3EtZGVsZXRlLWFsbCBzeW0gZW52KSkpCiAgICAgICAoZXZhbCAnKGZp bHRlcmVkLXBjYXNlIHZhbHMKICAgICAgICAgICAgICAgIChsYW1iZGEgKHgpCiAgICAgICAgICAg ICAgICAgIChhc3NxIHggZW52KSkKICAgICAgICAgICAgICAgICgsKGxpc3QgJ1xgIChtYXBjYXIg KGxhbWJkYSAoeCkgKGxpc3QgJ1wsIHgpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICBwYXRzKSkKICAgICAgICAgICAgICAgICAoZnVuY2FsbCAnLGZ1bmMgLEBhcmdsaXN0KSkp CiAgICAgICAgICAgICBlbnYpKSkpCgooZGVmdW4gYXJnbGlzdCAoZnVuYykKICAod2hpbGUgKGFu ZCAoc3ltYm9scCBmdW5jKQoJICAgICAgKHNldHEgZnVuYyAoc3ltYm9sLWZ1bmN0aW9uIGZ1bmMp KSkpCiAgKHBjYXNlIGZ1bmMKICAgICgob3IgYChsYW1iZGEgLGFyZ2xpc3QgLiAsYm9keSkKCSBg KGNsb3N1cmUgLGxleGVudiAsYXJnbGlzdCAuICxib2R5KSkKICAgICBhcmdsaXN0KQogICAgKF8g KGNkciAocmVhZAoJICAgICAoZG93bmNhc2UKCSAgICAgIChjYXIgKGhlbHAtc3BsaXQtZnVuZG9j IChkb2N1bWVudGF0aW9uIGZ1bmMgdCkgZnVuYyB0KSkpKSkpKSkKCihkZWZtYWNybyBwY2FsbCAo ZnVuYyAmcmVzdCBiaW5kaW5ncykKICAobGV0KiAoKHN5bXMgKHBjYWxsLWNvbGxlY3Qtc3ltYm9s cyBiaW5kaW5ncykpCiAgICAgICAgIChlbnYgKHBjYWxsLW1ha2UtZW52aXJvbm1lbnQgc3ltcykp CiAgICAgICAgIChwYXRzIChtYXBjYXIgIydjYXIgYmluZGluZ3MpKQogICAgICAgICAodmFscyAo bWFwY2FyICMnY2FkciBiaW5kaW5ncykpKQogIGAobGV0ICgoZnVuYyAnLGZ1bmMpKQogICAgICh3 aGlsZSAoYW5kIChzeW1ib2xwIGZ1bmMpCgkgICAgICAgICAoc2V0cSBmdW5jIChzeW1ib2wtZnVu Y3Rpb24gZnVuYykpKSkKICAgICAobGV0ICgocGNhbGxlciAoZnVuY2FsbCAjJ3BjYWxsZXIgZnVu YyAnLHBhdHMpKSkKICAgICAgIChsZXQqICgodW5ib3VuZC1zeW1zIChsaXN0IG5pbCkpCiAgICAg ICAgICAgICAgKGVudiAsZW52KQoJICAgICAgKHBjYXNlLS1lbnYgZW52KSkKICAgICAgICAgKGRv bGlzdCAoc3ltIHVuYm91bmQtc3ltcykKICAgICAgICAgICAoc2V0cSBlbnYgKGFzc3EtZGVsZXRl LWFsbCBzeW0gZW52KSkpCiAgICAgICAgIChmdW5jYWxsIHBjYWxsZXIgZW52IChsaXN0ICxAdmFs cykpKSkpKSkKCihkZWZ1biBwY2FzZS0tZXhwYW5kIChleHAgY2FzZXMgZmlsdGVyKQogIDs7ICht ZXNzYWdlICJwaWQ9JVMgKHBjYXNlLS1leHBhbmQgJVMgLi4uaGFzaD0lUykiCiAgOzsgICAgICAg ICAgKGVtYWNzLXBpZCkgZXhwIChzeGhhc2ggY2FzZXMpKQogIChtYWNyb2V4cC1sZXQyIG1hY3Jv ZXhwLWNvcHlhYmxlLXAgdmFsIGV4cAogICAgKGxldCogKChkZWZzICgpKQogICAgICAgICAgIChz ZWVuICcoKSkKICAgICAgICAgICAoY29kZWdlbgogICAgICAgICAgICAobGFtYmRhIChjb2RlIHZh cnMpCiAgICAgICAgICAgICAgKGxldCAoKHZhcnMgKHBjYXNlLS1mZ3JlcCB2YXJzIGNvZGUpKQog ICAgICAgICAgICAgICAgICAgIChwcmV2IChhc3NxIGNvZGUgc2VlbikpKQogICAgICAgICAgICAg ICAgKGlmIChub3QgcHJldikKICAgICAgICAgICAgICAgICAgICAobGV0ICgocmVzIChwY2FzZS1j b2RlZ2VuIGNvZGUgdmFycykpKQogICAgICAgICAgICAgICAgICAgICAgKHB1c2ggKGxpc3QgY29k ZSB2YXJzIHJlcykgc2VlbikKICAgICAgICAgICAgICAgICAgICAgIHJlcykKICAgICAgICAgICAg ICAgICAgOzsgU2luY2Ugd2UgdXNlIGEgdHJlZS1iYXNlZCBwYXR0ZXJuIG1hdGNoaW5nCiAgICAg ICAgICAgICAgICAgIDs7IHRlY2huaXF1ZSwgdGhlIGxlYXZlcyAodGhlIHBsYWNlcyB0aGF0IGNv bnRhaW4gdGhlCiAgICAgICAgICAgICAgICAgIDs7IGNvZGUgdG8gcnVuIG9uY2UgYSBwYXR0ZXJu IGlzIG1hdGNoZWQpIGNhbiBnZXQKICAgICAgICAgICAgICAgICAgOzsgY29waWVkIGEgdmVyeSBs YXJnZSBudW1iZXIgb2YgdGltZXMsIHNvIHRvIGF2b2lkCiAgICAgICAgICAgICAgICAgIDs7IGNv ZGUgZXhwbG9zaW9uLCB3ZSBuZWVkIHRvIGtlZXAgdHJhY2sgb2YgaG93IG1hbnkKICAgICAgICAg ICAgICAgICAgOzsgdGltZXMgd2UndmUgdXNlZCBlYWNoIGxlYWYgYW5kIG1vdmUgaXQKICAgICAg ICAgICAgICAgICAgOzsgdG8gYSBzZXBhcmF0ZSBmdW5jdGlvbiBpZiB0aGF0IG51bWJlciBpcyB0 b28gaGlnaC4KICAgICAgICAgICAgICAgICAgOzsKICAgICAgICAgICAgICAgICAgOzsgV2UndmUg YWxyZWFkeSB1c2VkIHRoaXMgYnJhbmNoLiAgU28gaXQgaXMgc2hhcmVkLgogICAgICAgICAgICAg ICAgICAobGV0KiAoKGNvZGUgKGNhciBwcmV2KSkgICAgICAgICAoY2RycHJldiAoY2RyIHByZXYp KQogICAgICAgICAgICAgICAgICAgICAgICAgKHByZXZ2YXJzIChjYXIgY2RycHJldikpICAoY2Rk cnByZXYgKGNkciBjZHJwcmV2KSkKICAgICAgICAgICAgICAgICAgICAgICAgIChyZXMgKGNhciBj ZGRycHJldikpKQogICAgICAgICAgICAgICAgICAgICh1bmxlc3MgKHN5bWJvbHAgcmVzKQogICAg ICAgICAgICAgICAgICAgICAgOzsgVGhpcyBpcyB0aGUgZmlyc3QgcmVwZWF0LCBzbyB3ZSBoYXZl IHRvIG1vdmUKICAgICAgICAgICAgICAgICAgICAgIDs7IHRoZSBicmFuY2ggdG8gYSBzZXBhcmF0 ZSBmdW5jdGlvbi4KICAgICAgICAgICAgICAgICAgICAgIChsZXQgKChic3ltCiAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgKG1ha2Utc3ltYm9sIChmb3JtYXQgInBjYXNlLSVkIiAobGVuZ3Ro IGRlZnMpKSkpKQogICAgICAgICAgICAgICAgICAgICAgICAocHVzaCBgKCxic3ltIChsYW1iZGEg LChtYXBjYXIgIydjYXIgcHJldnZhcnMpICxAY29kZSkpCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIGRlZnMpCiAgICAgICAgICAgICAgICAgICAgICAgIChzZXRjYXIgcmVzICdmdW5jYWxs KQogICAgICAgICAgICAgICAgICAgICAgICAoc2V0Y2RyIHJlcyAoY29ucyBic3ltIChtYXBjYXIg IydjZHIgcHJldnZhcnMpKSkKICAgICAgICAgICAgICAgICAgICAgICAgKHNldGNhciAoY2RkciBw cmV2KSBic3ltKQogICAgICAgICAgICAgICAgICAgICAgICAoc2V0cSByZXMgYnN5bSkpKQogICAg ICAgICAgICAgICAgICAgIChzZXRxIHZhcnMgKGNvcHktc2VxdWVuY2UgdmFycykpCiAgICAgICAg ICAgICAgICAgICAgKGxldCAoKGFyZ3MgKG1hcGNhciAobGFtYmRhIChwYSkKICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGxldCAoKHYgKGFzc3EgKGNhciBwYSkgdmFy cykpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXRxIHZh cnMgKGRlbHEgdiB2YXJzKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAoY2RyIHYpKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBy ZXZ2YXJzKSkpCiAgICAgICAgICAgICAgICAgICAgICA7OyBJZiBzb21lIG9mIGB2YXJzJyB3ZXJl IG5vdCBmb3VuZCBpbiBgcHJldnZhcnMnLCB0aGF0J3MKICAgICAgICAgICAgICAgICAgICAgIDs7 IE9LIGl0IGp1c3QgbWVhbnMgdGhvc2UgdmFycyBhcmVuJ3QgcHJlc2VudCBpbiBhbGwKICAgICAg ICAgICAgICAgICAgICAgIDs7IGJyYW5jaGVzLCBzbyB0aGV5IGNhbiBiZSB1c2VkIHdpdGhpbiB0 aGUgcGF0dGVybgogICAgICAgICAgICAgICAgICAgICAgOzsgKGUuZy4gYnkgYSBgZ3VhcmQvbGV0 L3ByZWQnKSBidXQgbm90IGluIHRoZSBicmFuY2guCiAgICAgICAgICAgICAgICAgICAgICA7OyBG SVhNRTogQnV0IGlmIHNvbWUgb2YgYHByZXZ2YXJzJyBhcmUgbm90IGluIGB2YXJzJyB3ZQogICAg ICAgICAgICAgICAgICAgICAgOzsgc2hvdWxkIHJlbW92ZSB0aGVtIGZyb20gYHByZXZ2YXJzJyEK ICAgICAgICAgICAgICAgICAgICAgIGAoZnVuY2FsbCAscmVzICxAYXJncykpKSkpKSkKICAgICAg ICAgICAodXNlZC1jYXNlcyAoKSkKICAgICAgICAgICAobWFpbgogICAgICAgICAgICAocGNhc2Ut LXUKICAgICAgICAgICAgIChtYXBjYXIgKGxhbWJkYSAoY2FzZSkKICAgICAgICAgICAgICAgICAg ICAgICBgKCwocGNhc2UtLW1hdGNoIHZhbCAocGNhc2UtLW1hY3JvZXhwYW5kIChjYXIgY2FzZSkp KQogICAgICAgICAgICAgICAgICAgICAgICAgLChsYW1iZGEgKHZhcnMpCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAodW5sZXNzIChtZW1xIGNhc2UgdXNlZC1jYXNlcykKICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgOzsgS2VlcCB0cmFjayBvZiB0aGUgY2FzZXMgdGhhdCBhcmUgdXNl ZC4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHB1c2ggY2FzZSB1c2VkLWNhc2VzKSkK ICAgICAgICAgICAgICAgICAgICAgICAgICAgIChmdW5jYWxsCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgKGlmIChwY2FzZS0tc21hbGwtYnJhbmNoLXAgKGNkciBjYXNlKSkKICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgOzsgRG9uJ3QgYm90aGVyIHNoYXJpbmcgbXVsdGlwbGUK ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOzsgb2NjdXJyZW5jZXMgb2YgdGhpcyBs ZWFmIHNpbmNlIGl0J3Mgc21hbGwuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChs YW1iZGEgKGNvZGUgdmFycykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocGNh c2UtY29kZWdlbiBjb2RlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgKHBjYXNlLS1mZ3JlcCB2YXJzIGNvZGUpKSkKICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIGNvZGVnZW4pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNkciBjYXNl KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcnMpKSkpCiAgICAgICAgICAgICAgICAg ICAgIGNhc2VzKQogICAgICAgICAgICAgZmlsdGVyKSkpCiAgICAgIChkb2xpc3QgKGNhc2UgY2Fz ZXMpCiAgICAgICAgKHVubGVzcyAob3IgKG1lbXEgY2FzZSB1c2VkLWNhc2VzKQogICAgICAgICAg ICAgICAgICAgIChtZW1xIChjYXIgY2FzZSkgcGNhc2UtLWRvbnR3YXJuLXVwYXRzKSkKICAgICAg ICAgIChtZXNzYWdlICJSZWR1bmRhbnQgcGNhc2UgcGF0dGVybjogJVMiIChjYXIgY2FzZSkpKSkK ICAgICAgKG1hY3JvZXhwLWxldCogZGVmcyBtYWluKSkpKQoKKGRlZnZhciBwY2FzZS0tZW52IG5p bCkKCihwY2FzZS1kZWZtYWNybyBjb25jYXQgKCZyZXN0IHBhdHRlcm5zKQogIChpZiBwYXR0ZXJu cwogICAgICAobGV0KiAoKHBhdCAobGlzdCAnXGAgKGNvbnMgKGxpc3QgJ1wsIChjYXIgcGF0dGVy bnMpKQoJCQkJICAobGlzdCAnXCwgKGNvbnMgJ2NvbmNhdAoJCQkJCQkgIChjZHIgcGF0dGVybnMp KSkpKSkKCSAgICAgKGYgYChsYW1iZGEgKGwpCgkJICAgKGNhdGNoICdwY2FzZS0tY2FsbAoJCSAg ICAgKGRvdGltZXMgKGkgKDErIChsZW5ndGggbCkpKQoJCSAgICAgICAobGV0KiAoKGxjIChjb25z IChzZXEtc3Vic2VxIGwgMCBpKQoJCQkJCShzZXEtc3Vic2VxIGwgaSkpKSkKCQkJIChmaWx0ZXJl ZC1wY2FzZSBsYwoJCQkgICAobGFtYmRhICh4KQoJCQkgICAgIChhc3NxIHggcGNhc2UtLWVudikp CgkJCSAgICgscGF0ICh0aHJvdyAncGNhc2UtLWNhbGwgbGMpKSkpKSkpKSkKCWAoYXBwICxmICxw YXQpKQogICAgYChwcmVkIHNlcS1lbXB0eS1wKSkpCgooZGVmbWFjcm8gZmlsdGVyZWQtcGNhc2Ug KGV4cCBmaWx0ZXIgJnJlc3QgY2FzZXMpCiAgKGRlY2xhcmUgKGluZGVudCAxKSAoZGVidWcgKGZv cm0gJnJlc3QgKHBjYXNlLVBBVCBib2R5KSkpKQogIChwY2FzZS0tZXhwYW5kIGV4cCBjYXNlcyBm aWx0ZXIpKQoKKGRlZm1hY3JvIHBjYXNlIChleHAgJnJlc3QgY2FzZXMpCiAgIkV2YWx1YXRlIEVY UCB0byBnZXQgRVhQVkFMOyB0cnkgcGFzc2luZyBjb250cm9sIHRvIG9uZSBvZiBDQVNFUy4KQ0FT RVMgaXMgYSBsaXN0IG9mIGVsZW1lbnRzIG9mIHRoZSBmb3JtIChQQVRURVJOIENPREUuLi4pLgpG b3IgdGhlIGZpcnN0IENBU0Ugd2hvc2UgUEFUVEVSTiBcIm1hdGNoZXNcIiBFWFBWQUwsCmV2YWx1 YXRlIGl0cyBDT0RFLi4uLCBhbmQgcmV0dXJuIHRoZSB2YWx1ZSBvZiB0aGUgbGFzdCBmb3JtLgpJ ZiBubyBDQVNFIGhhcyBhIFBBVFRFUk4gdGhhdCBtYXRjaGVzLCByZXR1cm4gbmlsLgoKRWFjaCBQ QVRURVJOIGV4cGFuZHMsIGluIGVzc2VuY2UsIHRvIGEgcHJlZGljYXRlIHRvIGNhbGwKb24gRVhQ VkFMLiAgV2hlbiB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoYXQgY2FsbCBpcyBub24tbmlsLApQQVRU RVJOIG1hdGNoZXMuICBQQVRURVJOIGNhbiB0YWtlIG9uZSBvZiB0aGUgZm9ybXM6CgogIF8gICAg ICAgICAgICAgICAgbWF0Y2hlcyBhbnl0aGluZy4KICBcXD0nVkFMICAgICAgICAgICAgIG1hdGNo ZXMgaWYgRVhQVkFMIGlzIGBlcXVhbCcgdG8gVkFMLgogIEtFWVdPUkQgICAgICAgICAgc2hvcnRo YW5kIGZvciBcXD0nS0VZV09SRAogIElOVEVHRVIgICAgICAgICAgc2hvcnRoYW5kIGZvciBcXD0n SU5URUdFUgogIFNUUklORyAgICAgICAgICAgc2hvcnRoYW5kIGZvciBcXD0nU1RSSU5HCiAgU1lN Qk9MICAgICAgICAgICBtYXRjaGVzIGFueXRoaW5nIGFuZCBiaW5kcyBpdCB0byBTWU1CT0wuCiAg ICAgICAgICAgICAgICAgICBJZiBhIFNZTUJPTCBpcyB1c2VkIHR3aWNlIGluIHRoZSBzYW1lIHBh dHRlcm4KICAgICAgICAgICAgICAgICAgIHRoZSBzZWNvbmQgb2NjdXJyZW5jZSBiZWNvbWVzIGFu IGBlcSd1YWxpdHkgdGVzdC4KICAocHJlZCBGVU4pICAgICAgIG1hdGNoZXMgaWYgRlVOIGNhbGxl ZCBvbiBFWFBWQUwgcmV0dXJucyBub24tbmlsLgogIChhcHAgRlVOIFBBVCkgICAgbWF0Y2hlcyBp ZiBGVU4gY2FsbGVkIG9uIEVYUFZBTCBtYXRjaGVzIFBBVC4KICAoZ3VhcmQgQk9PTEVYUCkgIG1h dGNoZXMgaWYgQk9PTEVYUCBldmFsdWF0ZXMgdG8gbm9uLW5pbC4KICAobGV0IFBBVCBFWFBSKSAg IG1hdGNoZXMgaWYgRVhQUiBtYXRjaGVzIFBBVC4KICAoYW5kIFBBVC4uLikgICAgIG1hdGNoZXMg aWYgYWxsIHRoZSBwYXR0ZXJucyBtYXRjaC4KICAob3IgUEFULi4uKSAgICAgIG1hdGNoZXMgaWYg YW55IG9mIHRoZSBwYXR0ZXJucyBtYXRjaGVzLgoKRlVOIGluIGBwcmVkJyBhbmQgYGFwcCcgY2Fu IHRha2Ugb25lIG9mIHRoZSBmb3JtczoKICBTWU1CT0wgIG9yICAobGFtYmRhIEFSR1MgQk9EWSkK ICAgICBjYWxsIGl0IHdpdGggb25lIGFyZ3VtZW50CiAgKEYgQVJHMSAuLiBBUkduKQogICAgIGNh bGwgRiB3aXRoIEFSRzEuLkFSR24gYW5kIEVYUFZBTCBhcyBuKzEndGggYXJndW1lbnQKCkZVTiwg Qk9PTEVYUCwgRVhQUiwgYW5kIHN1YnNlcXVlbnQgUEFUIGNhbiByZWZlciB0byB2YXJpYWJsZXMK Ym91bmQgZWFybGllciBpbiB0aGUgcGF0dGVybiBieSBhIFNZTUJPTCBwYXR0ZXJuLgoKQWRkaXRp b25hbCBwYXR0ZXJucyBjYW4gYmUgZGVmaW5lZCB1c2luZyBgcGNhc2UtZGVmbWFjcm8nLgoKU2Vl IEluZm8gbm9kZSBgKGVsaXNwKSBQYXR0ZXJuLU1hdGNoaW5nIENvbmRpdGlvbmFsJyBpbiB0aGUK RW1hY3MgTGlzcCBtYW51YWwgZm9yIG1vcmUgaW5mb3JtYXRpb24gYW5kIGV4YW1wbGVzLiIKICAo ZGVjbGFyZSAoaW5kZW50IDEpIChkZWJ1ZyAoZm9ybSAmcmVzdCAocGNhc2UtUEFUIGJvZHkpKSkp CiAgOzsgV2Ugd2FudCB0byB1c2UgYSB3ZWFrIGhhc2ggdGFibGUgYXMgYSBjYWNoZSwgYnV0IHRo ZSBrZXkgd2lsbCB1bmF2b2lkYWJseQogIDs7IGJlIGJhc2VkIG9uIGBleHAnIGFuZCBgY2FzZXMn LCB5ZXQgYGNhc2VzJyBpcyBhIGZyZXNoIG5ldyBsaXN0IGVhY2ggdGltZQogIDs7IHdlJ3JlIGNh bGxlZCBzbyBpdCdsbCBiZSBpbW1lZGlhdGVseSBHQydkLiAgU28gd2UgdXNlIChjYXIgY2FzZXMp IGFzIGtleQogIDs7IHdoaWNoIGRvZXMgY29tZSBzdHJhaWdodCBmcm9tIHRoZSBzb3VyY2UgY29k ZSBhbmQgc2hvdWxkIGhlbmNlIG5vdCBiZSBHQydkCiAgOzsgc28gZWFzaWx5LgogIChsZXQgKChk YXRhIChnZXRoYXNoIChjYXIgY2FzZXMpIHBjYXNlLS1tZW1vaXplKSkKICAgICAgICAoZmlsdGVy IG5pbCkpCiAgICA7OyBkYXRhID0gKEVYUCBDQVNFUyAuIEVYUEFOU0lPTikKICAgIChpZiAoYW5k IChlcXVhbCBleHAgKGNhciBkYXRhKSkgKGVxdWFsIGNhc2VzIChjYWRyIGRhdGEpKSkKICAgICAg ICA7OyBXZSBoYXZlIHRoZSByaWdodCBleHBhbnNpb24uCiAgICAgICAgKGNkZHIgZGF0YSkKICAg ICAgOzsgKHdoZW4gKGdldGhhc2ggKGNhciBjYXNlcykgcGNhc2UtLW1lbW9pemUtMSkKICAgICAg OzsgICAobWVzc2FnZSAicGNhc2UtbWVtb2l6ZSBmYWlsZWQgYmVjYXVzZSBvZiB3ZWFrIGtleSEh IikpCiAgICAgIDs7ICh3aGVuIChnZXRoYXNoIChjYXIgY2FzZXMpIHBjYXNlLS1tZW1vaXplLTIp CiAgICAgIDs7ICAgKG1lc3NhZ2UgInBjYXNlLW1lbW9pemUgZmFpbGVkIGJlY2F1c2Ugb2YgZXEg dGVzdCBvbiAlUyIKICAgICAgOzsgICAgICAgICAgICAoY2FyIGNhc2VzKSkpCiAgICAgIDs7ICh3 aGVuIGRhdGEKICAgICAgOzsgICAobWVzc2FnZSAicGNhc2UtbWVtb2l6ZTogZXF1YWwgZmlyc3Qg YnJhbmNoLCB5ZXQgZGlmZmVyZW50IikpCiAgICAgIChsZXQgKChleHBhbnNpb24gKHBjYXNlLS1l eHBhbmQgZXhwIGNhc2VzIGZpbHRlcikpKQogICAgICAgIChwdXRoYXNoIChjYXIgY2FzZXMpIGAo LGV4cCAsY2FzZXMgLEBleHBhbnNpb24pIHBjYXNlLS1tZW1vaXplKQogICAgICAgIDs7IChwdXRo YXNoIChjYXIgY2FzZXMpIGAoLGV4cCAsY2FzZXMgLEBleHBhbnNpb24pIHBjYXNlLS1tZW1vaXpl LTEpCiAgICAgICAgOzsgKHB1dGhhc2ggKGNhciBjYXNlcykgYCgsZXhwICxjYXNlcyAsQGV4cGFu c2lvbikgcGNhc2UtLW1lbW9pemUtMikKICAgICAgICBleHBhbnNpb24pKSkpCgooZGVmdW4gcGNh c2UtLXUgKGJyYW5jaGVzIGZpbHRlcikKICAiRXhwYW5kIG1hdGNoZXIgZm9yIHJ1bGVzIEJSQU5D SEVTLgpFYWNoIEJSQU5DSCBoYXMgdGhlIGZvcm0gKE1BVENIIENPREUgLiBWQVJTKSB3aGVyZQpD T0RFIGlzIHRoZSBjb2RlIGdlbmVyYXRvciBmb3IgdGhhdCBicmFuY2guClZBUlMgaXMgdGhlIHNl dCBvZiB2YXJzIGFscmVhZHkgYm91bmQgYnkgZWFybGllciBtYXRjaGVzLgpNQVRDSCBpcyB0aGUg cGF0dGVybiB0aGF0IG5lZWRzIHRvIGJlIG1hdGNoZWQsIG9mIHRoZSBmb3JtOgogIChtYXRjaCBW QVIgLiBQQVQpCiAgKGFuZCBNQVRDSCAuLi4pCiAgKG9yIE1BVENIIC4uLikiCiAgKHdoZW4gKHNl dHEgYnJhbmNoZXMgKGRlbHEgbmlsIGJyYW5jaGVzKSkKICAgIChsZXQqICgoY2FyYnJhbmNoIChj YXIgYnJhbmNoZXMpKQogICAgICAgICAgIChtYXRjaCAoY2FyIGNhcmJyYW5jaCkpIChjZGFyYnJh bmNoIChjZHIgY2FyYnJhbmNoKSkKICAgICAgICAgICAoY29kZSAoY2FyIGNkYXJicmFuY2gpKQog ICAgICAgICAgICh2YXJzIChjZHIgY2RhcmJyYW5jaCkpKQogICAgICAocGNhc2UtLXUxIChsaXN0 IG1hdGNoKSBjb2RlIHZhcnMgKGNkciBicmFuY2hlcykgZmlsdGVyKSkpKQoKKGRlZnVuIHBjYXNl LS11MSAobWF0Y2hlcyBjb2RlIHZhcnMgcmVzdCBmaWx0ZXIpCiAgIlJldHVybiBjb2RlIHRoYXQg cnVucyBDT0RFICh3aXRoIFZBUlMpIGlmIE1BVENIRVMgbWF0Y2guCk90aGVyd2lzZSwgaXQgZGVm ZXJzIHRvIFJFU1Qgd2hpY2ggaXMgYSBsaXN0IG9mIGJyYW5jaGVzIG9mIHRoZSBmb3JtClwoRUxT RS1NQVRDSCBFTFNFLUNPREUgLiBFTFNFLVZBUlMpLiIKICA7OyBEZXBlbmRpbmcgb24gdGhlIG9y ZGVyIGluIHdoaWNoIHdlIGNob29zZSB0byBjaGVjayBlYWNoIG9mIHRoZSBNQVRDSEVTLAogIDs7 IHRoZSByZXN1bHRpbmcgdHJlZSBtYXkgYmUgc21hbGxlciBvciBiaWdnZXIuICBTbyBpbiBnZW5l cmFsLCB3ZSdkIHdhbnQKICA7OyB0byBiZSBjYXJlZnVsIHRvIGNob3NlIHRoZSAib3B0aW1hbCIg b3JkZXIuICBCdXQgcHJlZGljYXRlCiAgOzsgcGF0dGVybnMgbWFrZSB0aGlzIGhhcmRlciBiZWNh dXNlIHRoZXkgY3JlYXRlIGRlcGVuZGVuY2llcwogIDs7IGJldHdlZW4gbWF0Y2hlcy4gIFNvIHdl IGRvbid0IGJvdGhlciB0cnlpbmcgdG8gcmVvcmRlciBhbnl0aGluZy4KICAoY29uZAogICAoKG51 bGwgbWF0Y2hlcykgKGZ1bmNhbGwgY29kZSB2YXJzKSkKICAgKChlcSA6cGNhc2UtLWZhaWwgKGNh ciBtYXRjaGVzKSkgKHBjYXNlLS11IHJlc3QgZmlsdGVyKSkKICAgKChlcSA6cGNhc2UtLXN1Y2Nl ZWQgKGNhciBtYXRjaGVzKSkKICAgIChwY2FzZS0tdTEgKGNkciBtYXRjaGVzKSBjb2RlIHZhcnMg cmVzdCBmaWx0ZXIpKQogICAoKGVxICdhbmQgKGNhYXIgbWF0Y2hlcykpCiAgICAocGNhc2UtLXUx IChhcHBlbmQgKGNkYXIgbWF0Y2hlcykgKGNkciBtYXRjaGVzKSkgY29kZSB2YXJzIHJlc3QKICAg ICAgICAgICAgICAgZmlsdGVyKSkKICAgKChlcSAnb3IgKGNhYXIgbWF0Y2hlcykpCiAgICAobGV0 KiAoKGFsdHMgKGNkYXIgbWF0Y2hlcykpCiAgICAgICAgICAgKHZhciAoaWYgKGVxIChjYWFyIGFs dHMpICdtYXRjaCkgKGNhZHIgKGNhciBhbHRzKSkpKQogICAgICAgICAgIChzaW1wbGVzICcoKSkg KG90aGVycyAnKCkpIChtZW0tZnVuICdtZW1xKSkKICAgICAgKHdoZW4gdmFyCiAgICAgICAgKGRv bGlzdCAoYWx0IGFsdHMpCiAgICAgICAgICAoaWYgKGFuZCAoZXEgKGNhciBhbHQpICdtYXRjaCkg KGVxIHZhciAoY2FkciBhbHQpKQogICAgICAgICAgICAgICAgICAgKGxldCAoKHVwYXQgKGNkZHIg YWx0KSkpCiAgICAgICAgICAgICAgICAgICAgIChlcSAoY2FyLXNhZmUgdXBhdCkgJ3F1b3RlKSkp CiAgICAgICAgICAgICAgKGxldCAoKHZhbCAoY2FkciAoY2RkciBhbHQpKSkpCiAgICAgICAgICAg ICAgICAoY29uZCAoKGludGVnZXJwIHZhbCkKICAgICAgICAgICAgICAgICAgICAgICAod2hlbiAo ZXEgbWVtLWZ1biAnbWVtcSkKICAgICAgICAgICAgICAgICAgICAgICAgIChzZXRxIG1lbS1mdW4g J21lbXFsKSkpCiAgICAgICAgICAgICAgICAgICAgICAoKG5vdCAoc3ltYm9scCB2YWwpKQogICAg ICAgICAgICAgICAgICAgICAgIChzZXRxIG1lbS1mdW4gJ21lbWJlcikpKQogICAgICAgICAgICAg ICAgKHB1c2ggdmFsIHNpbXBsZXMpKQogICAgICAgICAgICAocHVzaCBhbHQgb3RoZXJzKSkpKQog ICAgICAoY29uZAogICAgICAgKChudWxsIGFsdHMpIChlcnJvciAiUGxlYXNlIGF2b2lkIGl0Iikg KHBjYXNlLS11IHJlc3QgZmlsdGVyKSkKICAgICAgIDs7IFllcywgd2UgY2FuIHVzZSBgbWVtcWwn IChvciBgbWVtYmVyJykhCiAgICAgICAoKD4gKGxlbmd0aCBzaW1wbGVzKSAxKQogICAgICAgIChw Y2FzZS0tdTEgKGNvbnMgYChtYXRjaCAsdmFyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIC4gKHByZWQgKHBjYXNlLS1mbGlwICxtZW0tZnVuICcsc2ltcGxlcykpKQogICAgICAgICAg ICAgICAgICAgICAgICAgKGNkciBtYXRjaGVzKSkKICAgICAgICAgICAgICAgICAgIGNvZGUgdmFy cwogICAgICAgICAgICAgICAgICAgKGlmIChudWxsIG90aGVycykgcmVzdAogICAgICAgICAgICAg ICAgICAgICAoY29ucyAoY29ucwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKHBjYXNlLS1h bmQgKGlmIChjZHIgb3RoZXJzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIChjb25zICdvciAobnJldmVyc2Ugb3RoZXJzKSkKICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgKGNhciBvdGhlcnMpKQogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgKGNkciBtYXRjaGVzKSkKICAgICAgICAgICAgICAgICAgICAgICAg ICAgIChjb25zIGNvZGUgdmFycykpCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3QpKQog ICAgICAgICAgICAgICAgICAgZmlsdGVyKSkKICAgICAgICh0CiAgICAgICAgKHBjYXNlLS11MSAo Y29ucyAocG9wIGFsdHMpIChjZHIgbWF0Y2hlcykpIGNvZGUgdmFycwogICAgICAgICAgICAgICAg ICAgKGlmIChudWxsIGFsdHMpIChwcm9nbiAoZXJyb3IgIlBsZWFzZSBhdm9pZCBpdCIpIHJlc3Qp CiAgICAgICAgICAgICAgICAgICAgIChjb25zIChjb25zCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAocGNhc2UtLWFuZCAoaWYgKGNkciBhbHRzKQogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIChjb25zICdvciBhbHRzKSAoY2FyIGFsdHMpKQogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNkciBtYXRjaGVzKSkKICAgICAgICAgICAg ICAgICAgICAgICAgICAgIChjb25zIGNvZGUgdmFycykpCiAgICAgICAgICAgICAgICAgICAgICAg ICAgIHJlc3QpKQogICAgICAgICAgICAgICAgICAgZmlsdGVyKSkpKSkKICAgKChlcSAnbWF0Y2gg KGNhYXIgbWF0Y2hlcykpCiAgICAobGV0KiAoKHBvcG1hdGNoZXMgKHBvcCBtYXRjaGVzKSkKICAg ICAgICAgICAoX29wIChjYXIgcG9wbWF0Y2hlcykpICAgICAgKGNkcnBvcG1hdGNoZXMgKGNkciBw b3BtYXRjaGVzKSkKICAgICAgICAgICAoc3ltIChjYXIgY2RycG9wbWF0Y2hlcykpCiAgICAgICAg ICAgKHVwYXQgKGNkciBjZHJwb3BtYXRjaGVzKSkpCiAgICAgIChjb25kCiAgICAgICAoKG1lbXEg dXBhdCAnKHQgXykpCiAgICAgICAgKGxldCAoKGNvZGUgKHBjYXNlLS11MSBtYXRjaGVzIGNvZGUg dmFycyByZXN0IGZpbHRlcikpKQogICAgICAgICAgKGlmIChlcSB1cGF0ICdfKSBjb2RlCiAgICAg ICAgICAgIChtYWNyb2V4cC0td2Fybi1hbmQtcmV0dXJuCiAgICAgICAgICAgICAiUGF0dGVybiB0 IGlzIGRlcHJlY2F0ZWQuICBVc2UgYF8nIGluc3RlYWQiCiAgICAgICAgICAgICBjb2RlKSkpKQog ICAgICAgKChlcSB1cGF0ICdwY2FzZS0tZG9udGNhcmUpIDpwY2FzZS0tZG9udGNhcmUpCiAgICAg ICAoKG1lbXEgKGNhci1zYWZlIHVwYXQpICcoZ3VhcmQgcHJlZCkpCiAgICAgICAgKGlmIChlcSAo Y2FyIHVwYXQpICdwcmVkKSAocGNhc2UtLW1hcmstdXNlZCBzeW0pKQogICAgICAgIChsZXQqICgo c3BsaXRyZXN0CiAgICAgICAgICAgICAgICAocGNhc2UtLXNwbGl0LXJlc3QKICAgICAgICAgICAg ICAgICBzeW0gKGxhbWJkYSAocGF0KSAocGNhc2UtLXNwbGl0LXByZWQgdmFycyB1cGF0IHBhdCkp IHJlc3QpKQogICAgICAgICAgICAgICAodGhlbi1yZXN0IChjYXIgc3BsaXRyZXN0KSkKICAgICAg ICAgICAgICAgKGVsc2UtcmVzdCAoY2RyIHNwbGl0cmVzdCkpKQogICAgICAgICAgKHBjYXNlLS1p ZiAoaWYgKGVxIChjYXIgdXBhdCkgJ3ByZWQpCiAgICAgICAgICAgICAgICAgICAgICAgICAocGNh c2UtLWZ1bmNhbGwgKGNhZHIgdXBhdCkgc3ltIHZhcnMpCiAgICAgICAgICAgICAgICAgICAgICAg KHBjYXNlLS1ldmFsIChjYWRyIHVwYXQpIHZhcnMpKQogICAgICAgICAgICAgICAgICAgICAocGNh c2UtLXUxIG1hdGNoZXMgY29kZSB2YXJzIHRoZW4tcmVzdCBmaWx0ZXIpCiAgICAgICAgICAgICAg ICAgICAgIChwY2FzZS0tdSBlbHNlLXJlc3QgZmlsdGVyKSkpKQogICAgICAgKChhbmQgKHN5bWJv bHAgdXBhdCkgdXBhdCkKICAgICAgICAocGNhc2UtLW1hcmstdXNlZCBzeW0pCiAgICAgICAgKGNv bmQKICAgICAgICAgKChhbmQgZmlsdGVyIChmdW5jYWxsIGZpbHRlciB1cGF0KSkKICAgICAgICAg IChwY2FzZS0tdTEgKGNvbnMgYChtYXRjaCAsc3ltIC4gKHByZWQgKGxhbWJkYSAoeCkgKGVxdWFs ICwoY2RyIChmdW5jYWxsIGZpbHRlciB1cGF0KSkgeCkpKSkKICAgICAgICAgICAgICAgICAgICAg ICAgICAgbWF0Y2hlcykKICAgICAgICAgICAgICAgICAgICAgY29kZSB2YXJzIHJlc3QgZmlsdGVy KSkKICAgICAgICAgKChub3QgKGFzc3EgdXBhdCB2YXJzKSkKICAgICAgICAgIChwY2FzZS0tdTEg bWF0Y2hlcyBjb2RlIChjb25zIChjb25zIHVwYXQgc3ltKSB2YXJzKSByZXN0IGZpbHRlcikpCiAg ICAgICAgICg7OyBOb24tbGluZWFyIHBhdHRlcm4uICBUdXJuIGl0IGludG8gYW4gYGVxJyB0ZXN0 LgogICAgICAgICAgKHBjYXNlLS11MSAoY29ucyBgKG1hdGNoICxzeW0gLiAocHJlZCAoZXEgLChj ZHIgKGFzc3EgdXBhdCB2YXJzKSkpKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hl cykKICAgICAgICAgICAgICAgICAgICAgY29kZSB2YXJzIHJlc3QgZmlsdGVyKSkpKQogICAgICAg KChlcSAoY2FyLXNhZmUgdXBhdCkgJ2xldCkKICAgICAgICA7OyBBIHVwYXQgb2YgdGhlIGZvcm0g KGxldCBWQVIgRVhQKS4KICAgICAgICA7OyAocGNhc2UtLXUxIG1hdGNoZXMgY29kZQogICAgICAg IDs7ICAgICAgICAgICAgKGNvbnMgKGNvbnMgKG50aCAxIHVwYXQpIChudGggMiB1cGF0KSkgdmFy cykgcmVzdCkKICAgICAgICAobWFjcm9leHAtbGV0MgogICAgICAgICAgICBtYWNyb2V4cC1jb3B5 YWJsZS1wIHN5bQogICAgICAgICAgICAocGNhc2UtLWV2YWwgKG50aCAyIHVwYXQpIHZhcnMpCiAg ICAgICAgICAocGNhc2UtLXUxIChjb25zIChwY2FzZS0tbWF0Y2ggc3ltIChudGggMSB1cGF0KSkg bWF0Y2hlcykKICAgICAgICAgICAgICAgICAgICAgY29kZSB2YXJzIHJlc3QgZmlsdGVyKSkpCiAg ICAgICAoKGVxIChjYXItc2FmZSB1cGF0KSAnYXBwKQogICAgICAgIDs7IEEgdXBhdCBvZiB0aGUg Zm9ybSAoYXBwIEZVTiBQQVQpCiAgICAgICAgKHBjYXNlLS1tYXJrLXVzZWQgc3ltKQogICAgICAg IChsZXQqICgoZnVuIChudGggMSB1cGF0KSkKICAgICAgICAgICAgICAgKG5zeW0gKGdlbnN5bSAi eCIpKQogICAgICAgICAgICAgICAoYm9keQogICAgICAgICAgICAgICAgOzsgV2UgZG9uJ3QgY2hh bmdlIGBtYXRjaGVzJyB0byByZXVzZSB0aGUgbmV3bHkgY29tcHV0ZWQgdmFsdWUsCiAgICAgICAg ICAgICAgICA7OyBiZWNhdXNlIHdlIGFzc3VtZSB0aGVyZSBzaG91bGRuJ3QgYmUgc3VjaCByZWR1 bmRhbmN5IGluIHRoZXJlLgogICAgICAgICAgICAgICAgKHBjYXNlLS11MSAoY29ucyAocGNhc2Ut LW1hdGNoIG5zeW0gKG50aCAyIHVwYXQpKSBtYXRjaGVzKQogICAgICAgICAgICAgICAgICAgICAg ICAgICBjb2RlIHZhcnMKICAgICAgICAgICAgICAgICAgICAgICAgICAgKHBjYXNlLS1hcHAtc3Vi c3QtcmVzdCByZXN0IHN5bSBmdW4gbnN5bSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgKGxh bWJkYSAoeCkgKGFuZCAobm90IChlcSB4IG5zeW0pKSkgKGFuZCBmaWx0ZXIgKGZ1bmNhbGwgZmls dGVyIHgpKSkpKSkKICAgICAgICAgIChpZiAobm90IChnZXQgbnN5bSAncGNhc2UtdXNlZCkpCiAg ICAgICAgICAgICAgYm9keQogICAgICAgICAgICAobWFjcm9leHAtbGV0KgogICAgICAgICAgICAg YCgoLG5zeW0gLChwY2FzZS0tZnVuY2FsbCBmdW4gc3ltIHZhcnMpKSkKICAgICAgICAgICAgIGJv ZHkpKSkpCiAgICAgICAoKGVxIChjYXItc2FmZSB1cGF0KSAncXVvdGUpCiAgICAgICAgKHBjYXNl LS1tYXJrLXVzZWQgc3ltKQogICAgICAgIChsZXQqICgodmFsIChjYWRyIHVwYXQpKQogICAgICAg ICAgICAgICAoc3BsaXRyZXN0IChwY2FzZS0tc3BsaXQtcmVzdAogICAgICAgICAgICAgICAgICAg ICAgICAgICBzeW0gKGxhbWJkYSAocGF0KSAocGNhc2UtLXNwbGl0LWVxdWFsIHZhbCBwYXQpKSBy ZXN0KSkKICAgICAgICAgICAgICAgKHRoZW4tcmVzdCAoY2FyIHNwbGl0cmVzdCkpCiAgICAgICAg ICAgICAgIChlbHNlLXJlc3QgKGNkciBzcGxpdHJlc3QpKSkKICAgICAgICAgIChwY2FzZS0taWYg KGNvbmQKICAgICAgICAgICAgICAgICAgICAgICgobnVsbCB2YWwpIGAobnVsbCAsc3ltKSkKICAg ICAgICAgICAgICAgICAgICAgICgoaW50ZWdlcnAgdmFsKSBgKGVxbCAsc3ltICx2YWwpKQogICAg ICAgICAgICAgICAgICAgICAgKChzeW1ib2xwIHZhbCkKICAgICAgICAgICAgICAgICAgICAgICAo aWYgKHBjYXNlLS1zZWxmLXF1b3RpbmctcCB2YWwpCiAgICAgICAgICAgICAgICAgICAgICAgICAg IGAoZXEgLHN5bSAsdmFsKQogICAgICAgICAgICAgICAgICAgICAgICAgYChlcSAsc3ltICcsdmFs KSkpCiAgICAgICAgICAgICAgICAgICAgICAodCBgKGVxdWFsICxzeW0gJyx2YWwpKSkKICAgICAg ICAgICAgICAgICAgICAgKHBjYXNlLS11MSBtYXRjaGVzIGNvZGUgdmFycyB0aGVuLXJlc3QgZmls dGVyKQogICAgICAgICAgICAgICAgICAgICAocGNhc2UtLXUgZWxzZS1yZXN0IGZpbHRlcikpKSkK ICAgICAgICgoZXEgKGNhci1zYWZlIHVwYXQpICdub3QpCiAgICAgICAgOzsgRklYTUU6IFRoZSBp bXBsZW1lbnRhdGlvbiBiZWxvdyBpcyBuYWl2ZSBhbmQgcmVzdWx0cyBpbgogICAgICAgIDs7IGlu ZWZmaWNpZW50IGNvZGUuCiAgICAgICAgOzsgVG8gbWFrZSBpdCB3b3JrIHJpZ2h0LCB3ZSB3b3Vs ZCBuZWVkIHRvIHR1cm4gcGNhc2UtLXUxJ3MKICAgICAgICA7OyBgY29kZScgYW5kIGB2YXJzJyBp bnRvIGEgc2luZ2xlIGFyZ3VtZW50IG9mIHRoZSBzYW1lIGZvcm0gYXMKICAgICAgICA7OyBgcmVz dCcuICBXZSB3b3VsZCBhbHNvIG5lZWQgdG8gc3BsaXQgdGhpcyBuZXcgYHRoZW4tcmVzdCcgYXJn dW1lbnQKICAgICAgICA7OyBmb3IgZXZlcnkgdGVzdCAoY3VycmVudGx5IHdlIGRvbid0IGJvdGhl ciB0byBkbyBpdCBzaW5jZQogICAgICAgIDs7IGl0J3Mgb25seSB1c2VmdWwgZm9yIG9kZCBwYXR0 ZXJucyBsaWtlIChhbmQgYChQQVQxIC4gUEFUMikKICAgICAgICA7OyBgKFBBVDMgLiBQQVQ0KSkg d2hpY2ggdGhlIHByb2dyYW1tZXIgY2FuIGVhc2lseSByZXdyaXRlCiAgICAgICAgOzsgdG8gdGhl IG1vcmUgZWZmaWNpZW50IGAoLChhbmQgUEFUMSBQQVQzKSAuICwoYW5kIFBBVDIgUEFUNCkpKS4K ICAgICAgICAocGNhc2UtLXUxIGAoKG1hdGNoICxzeW0gLiAsKGNhZHIgdXBhdCkpKQogICAgICAg ICAgICAgICAgICAgOzsgRklYTUU6IFRoaXMgY29kZWdlbiBpcyBub3QgY2FyZWZ1bCB0byBzaGFy ZSBpdHMKICAgICAgICAgICAgICAgICAgIDs7IGNvZGUgaWYgdXNlZCBzZXZlcmFsIHRpbWVzOiBj b2RlIGJsb3cgdXAgaXMgbGlrZWx5LgogICAgICAgICAgICAgICAgICAgKGxhbWJkYSAoX3ZhcnMp CiAgICAgICAgICAgICAgICAgICAgIDs7IGB2YXJzJyB3aWxsIGxpa2VseSBjb250YWluIGJpbmRp bmdzIHdoaWNoIGFyZQogICAgICAgICAgICAgICAgICAgICA7OyBub3QgYWx3YXlzIGF2YWlsYWJs ZSBpbiBvdGhlciBwYXRocyB0bwogICAgICAgICAgICAgICAgICAgICA7OyBgcmVzdCcsIHNvIHRo ZXJlJyBubyBwb2ludCB0cnlpbmcgdG8gcGFzcwogICAgICAgICAgICAgICAgICAgICA7OyB0aGVt IGRvd24uCiAgICAgICAgICAgICAgICAgICAgIChwY2FzZS0tdSByZXN0IGZpbHRlcikpCiAgICAg ICAgICAgICAgICAgICB2YXJzCiAgICAgICAgICAgICAgICAgICAobGlzdCBgKChhbmQgLiAsbWF0 Y2hlcykgLGNvZGUgLiAsdmFycykpCiAgICAgICAgICAgICAgICAgICBmaWx0ZXIpKQogICAgICAg KHQgKGVycm9yICJVbmtub3duIHBhdHRlcm4gYCVTJyIgdXBhdCkpKSkpCiAgICh0IChlcnJvciAi SW5jb3JyZWN0IE1BVENIICVTIiAoY2FyIG1hdGNoZXMpKSkpKQoKKGxldCAoKHNwYWNlICIgIikp CiAgKHBjYWxsIGYgKChjb25jYXQgaGVsbG8gc3BhY2Ugd29ybGQpICJoZWxsbyB3b3JsZCIpKSkK CihkZWZ1biBwY2FzZS0tbGVuZ3RoIChwYXR0ZXJuKQogICAgKHNldHEgcGF0dGVybiAocGNhc2Ut LW1hY3JvZXhwYW5kIHBhdHRlcm4pKQogICAgKHBjYXNlIHBhdHRlcm4KICAgICAgKGAocHJlZCBu dWxsKSAoY29ucyAwIDApKQogICAgICAoYCduaWwgKGNvbnMgMCAwKSkKICAgICAgKGAocHJlZCBj b25zcCkgKGNvbnMgMSAxLjBlK0lORikpCiAgICAgIChgKGFwcCBjZHIgLHBhdHRlcm4pCiAgICAg ICAobGV0ICgobGVuZ3RoIChwY2FzZS0tbGVuZ3RoIHBhdHRlcm4pKSkKCSAoaWYgKD4gKGNhciBs ZW5ndGgpIDApCgkgICAgIChjb25zICgxKyAoY2FyIGxlbmd0aCkpICgxKyAoY2RyIGxlbmd0aCkp KQoJICAgKGNvbnMgMCAoMSsgKGNkciBsZW5ndGgpKSkpKSkKICAgICAgKGAob3IgLiAscGF0dGVy bnMpCiAgICAgICAobGV0ICgoaW5mIDApCgkgICAgIChzdXAgMS4wZStJTkYpKQoJIChkb2xpc3Qg KHBhdHRlcm4gcGF0dGVybnMpCgkgICAobGV0KiAoKGlzIChwY2FzZS0tbGVuZ3RoIHBhdHRlcm4p KQoJCSAgKGkgKGNhciBpcykpCgkJICAocyAoY2RyIGlzKSkpCgkgICAgIChzZXRxIGluZiAobWlu IGluZiBpKSkKCSAgICAgKHNldHEgc3VwIChtYXggc3VwIHMpKSkpCgkgKGNvbnMgaW5mIHN1cCkp KQogICAgICAoYChhbmQgLiAscGF0dGVybnMpCiAgICAgICAobGV0ICgoaW5mIDApCgkgICAgIChz dXAgMS4wZStJTkYpKQoJIChkb2xpc3QgKHBhdHRlcm4gcGF0dGVybnMpCgkgICAobGV0KiAoKGlz IChwY2FzZS0tbGVuZ3RoIHBhdHRlcm4pKQoJCSAgKGkgKGNhciBpcykpCgkJICAocyAoY2RyIGlz KSkpCgkgICAgIChzZXRxIGluZiAobWF4IGluZiBpKSkKCSAgICAgKHNldHEgc3VwIChtaW4gc3Vw IHMpKSkpCgkgKGNvbnMgaW5mIHN1cCkpKQogICAgICAoXyAoY29ucyAwIDEuMGUrSU5GKSkpKQoK KHBjYXNlLWRlZm1hY3JvIG5vdCAocGF0KQogIGAoYXBwIChsYW1iZGEgKGV4cHZhbCkgKG5vdCAo cGNhc2UgZXhwdmFsICgscGF0IHQpKSkpCiAgICAgICAgKHByZWQgaWRlbnRpdHkpKSkK --0000000000009fed8e05ae317999-- From debbugs-submit-bounces@debbugs.gnu.org Mon Aug 31 23:12:16 2020 Received: (at 43100) by debbugs.gnu.org; 1 Sep 2020 03:12:16 +0000 Received: from localhost ([127.0.0.1]:54384 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCwiV-0006GE-PJ for submit@debbugs.gnu.org; Mon, 31 Aug 2020 23:12:16 -0400 Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:38203) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kCwiS-0006G1-OD for 43100@debbugs.gnu.org; Mon, 31 Aug 2020 23:12:14 -0400 Received: from pmg3.iro.umontreal.ca (localhost [127.0.0.1]) by pmg3.iro.umontreal.ca (Proxmox) with ESMTP id 00360440982; Mon, 31 Aug 2020 23:12:07 -0400 (EDT) Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg3.iro.umontreal.ca (Proxmox) with ESMTP id 25CC0440974; Mon, 31 Aug 2020 23:12:04 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1598929924; bh=DCdEyolyq9aa5hubzW4ZJy1RsTqh2AlSNBlOVyp/IE0=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From; b=HFJ+8QN8l7W3YWTJ8vZoCke2JScP+FZdVzo6SJhKOPpmD2C9w8v5+MtxgJ2F8kN2s s6zXkOBbKzE0RMSGimiQd1WJQNt2cfpHrdqJxxyQOF44HCvPEFv6tDpRkhnVv3AqWp OhkNnVOTBoolB54468I9wTZmbp9F5f/jRV/sYIXMlvRsBw7ZcPPCrIQFS4qn3JXI4K x5vA0TMPgcFlLNsME4LRKYmDFrChcWJjH6Gpu8+RBi253wdTgz7em9o334bRvCgwAy 3wRLvajpFmNEZ/2/hrkYWEmdWd7AsFsjO/LKCl2jYZAQIwJ4u+FhwuR3R3zwwWXgED whQWyDIj7vD1w== Received: from alfajor (unknown [45.72.232.131]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id E66A412078A; Mon, 31 Aug 2020 23:12:03 -0400 (EDT) From: Stefan Monnier To: Pip Cet Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally Message-ID: References: Date: Mon, 31 Aug 2020 23:12:02 -0400 In-Reply-To: (Pip Cet's message of "Mon, 31 Aug 2020 19:32:43 +0000") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-SPAM-INFO: Spam detection results: 0 ALL_TRUSTED -1 Passed through trusted hosts only via SMTP AWL -0.038 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain T_FILL_THIS_FORM_SHORT 0.01 Fill in a short form with personal information X-SPAM-LEVEL: X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 43100 Cc: Philipp Stephani , 43100@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) >> >> IIUC you want >> >> >> >> (pcase V >> >> ((or (pred symbolp) name) >> >> (let ((foo 'bar)) name))) >> >> >> >> to behave like >> >> >> >> (cond >> >> ((symbolp V) (let ((foo 'bar)) name)) >> >> (t (let ((name V)) (let ((foo 'bar)) name)))) >> >> >> >> ? >> > >> > Yes, that's correct. It's also how (pcase V ((or (pred symbolp) name) >> > name) behaves... >> >> Indeed, but that's an accident. Ideally it should either signal an >> error at macro-expansion time, or return nil when V is a symbol. > So, as I half-expected, the reaction to "pcase isn't powerful enough" > is "let's make it less powerful" :-) Your words, not mine. BTW, you can get (more or less) the behavior you want with: (pcase V ((or (and (pred symbolp) (let name name)) name) (let ((foo 'bar)) name))) [ The "more or less" is because when V is a symbol, the `name` within the body of the branch will not refer to the presumed surrounding binding of `name` but to a new binding also called `name` which temporarily hides the outer binding but is initialized to the same value. The difference only kicks in if one of those bindings is mutated. ] > Seriously, I get the impression you strongly feel pcase shouldn't be > (more) powerful, it should instead make non-explicit but fairly strong > complexity promises. I just want the complexity to be predictable without having to guess which optimization will be applicable. It's sometimes hard to satisfy this desire, admittedly. But note that it doesn't require the code to be "efficient": your `append` very much satisfies my desire since its complexity is very much predictable. > I disagree: in practice, complexity promises and optimization based on > them are often unnecessary. In fact, there's a Lisp tradition of using > assq and memq rather than building ad-hoc hash tables, even though > that often means run time is theoretically O(n^2) rather than O(n > log(n)). The complexity of `assq` is arguably bad, but it is very much predictable. >> More specifically, I'd rather not choose a semantics that imposes >> duplicating the branch body, since we have no control over its size and >> that can hence lead to potential code size explosion. > You're right, and it's a good thing that the duplication of the branch > body is a fixable implementation detail rather than something imposed > by the semantics. It's only fixable if you disregard the "more or less" above. I find it to be a pretty bad wrinkle in the semantics. >> The design of `pcase` assumes you want to optimize away the tests that >> are common to the various patterns. That can't be done with dynamic >> patterns. > Or it's a bit more difficult, at least... I think it's more than "a bit more difficult", because deciding how to optimize the tests will almost always take significantly more time than just doing the tests. So in order to do it dynamically and be useful, you still need to have 2 stages, where you optimize at one stage and then use the result several times later (to recoup the cost of the optimization). > The difficult part, in fact, is deciding that we want the arglist to > be part of the exposed function API: given an "arglist" function, the > rest of the implementation seems unproblematic, We have `help-function-arglist`, so it's not that hard. But it's not guaranteed to work. > though some workarounds for lexical binding are required (if nothing > else, this is an interesting exercise in how painful lexical binding > can be to work with). It's more of a philosophical issue. Lexical scoping fundamentally means that variables don't have names: (lambda (x) x) and (lambda (y) y) should be indistinguishable (that's what =CE=B1-renaming says, anyway). Obviously, `help-function-arglist` begs to differ, but I like lexical scoping so I'd rather we keep such exceptions to a minimum. >> So it's more like my option of returning nil, except it would return >> the value of a surrounding `name` variable? That could be done, but I'm >> not convinced it'd be more often useful. > > I started out with a fairly explicit practical problem: parsing GCC > machine descriptions, which are (essentially) sexps but have made the > mistake of having "optional" non-final parts, and I think it would be > great to express that in a pcase pattern, both for the obvious reasons > of legibility and for some non-obvious reasons of my own. I'm sorry, I don't understand what those sexps (and their =C2=ABoptional" non-final parts=C2=BB) have to do with pcase's handling of `or` patterns where the different branches don't bind the same set of variables. >> > disallowing the modification of name in X. >> That's rather hard to do (and I don't see what would be the benefit here= ). > I meant adding a cautionary note about it in the documentation, not > actively preventing it. So we're replacing the current "don't do that" with another "don't do that", neither of which is detected by the byte-compiler? I'd rather fix it "right" with something with a clean and simple semantics where the things you shouldn't do get properly flagged during compilation. > If we had read-only bindings, pcase would probably use them, > but we don't. We could add them, tho (I think it would be technically fairly easy, it's more a question of surface-language design, figuring out the right color of the bikeshed and deciding whether it's really worth adding this extra complexity into the language). I love immutable variables as much as the next guy, yet I have resisted the urge to add them to Elisp so far. >> The current implementation amounts to "we should signal an error but we >> don't bother doing so and just warn against it in the manual". >> Patch welcome ;-) > You mean a patch that would make pcase less powerful by making what I > want to do impossible rather than merely difficult? The way I see it, it would make what you want to do possible because what you suggest would merely give meaning to programs previously invalid. In contrast, with the current behavior your proposal implies breaking backward compatibility. >> >> I don't know of a simple implementation. >> > Here's my better-than-nothing attempt. I don't think that's complex; >> > if anything, it's too trivial. >> So you give it a search-based semantics. > I don't think the semantics are at all unclear, You misunderstood: I definitely didn't mean "unclear" when wrote "search-ba= sed". The semantics are definitely clear. >> The problem with it for me is that if we turn >> >> `(,a ,@b) >> >> into >> >> (append `(,a) b) > > List-final ,@ is too special, IMHO, to be turned into an (append) > pattern at all. So you want some ,@ to be turned into `append` and some not? That's exactly what I don't want, since it makes the performance unpredictable unless you know the details of the optimization. >> the pcase match will take a lot more time than the equivalent >> `(,a . ,b) >> Of course, you can try and handle these "easy" cases more efficiently, >> but then your ,@ will sometimes be very cheap and sometimes very >> expensive (depending on when an optimization can be applied), which >> I think is a misfeature (it's for this same reason that I dislike CL >> keyword arguments for functions). > I think it's an implementation detail. I don't want implementation details to choose between O(N) and O(1). This is the kind of "detail" that should be chosen by the author. > Some reasoning about the minimum and maximum length of sequences > matched by pcase patterns could help ordinary pcases, too, though: Potentially, of course. There are many options when it comes to the actual code generated by `pcase`. > (pcase '(a b c d) > (`(,a ,b ,c ,d) (list a b c d))) > > could call (pcase--check-length EXPVAL 4 4) rather than calling consp > four times, potentially descending into expensive predicates that are > unnecessary. But that presumes a C implementation of `pcase--check-length` since (< (length X) 4) can be a very bad idea when X is a long list. > It's strange to read quotes that yo ...? > Again, I think that's a fundamental difference between us when it > comes to the philosophy behind pcase. If I understand you correctly, > you deliberately want to limit pcase, moving away from the intuitive > definition of it that I gave above, because there might be a situation > in which people expect better performance than our limited > implementation can give them. Is that correct? [ The intuitive definition you gave doesn't work for most of the core patterns in `pcase` (e.g. `pred`, `app`, `let`, `guard`), so while it's fine as a guiding intuition, it can't be used to really define the intended semantics. ] No, the problem is not really one of performance, but rather one of defining which variables are in scope within a branch such that a given branch always has the same set of bindings within its scope, no matter how the pattern was matched, which I think gives it a cleaner and simpler semantics. [ It is also linked to a potential problem of code size explosion, admittedly. ] > I think that's a weak reason for a strong limitation, but of course > those are subjective questions. I don't see what strong limitation you're referring to. Having `name` get the value of a surrounding `name` instead of nil seems like a very minor issue and definitely not a "strong limitation". > For example, I don't expect (pcase 9 ((* x x) x)) to work, With an appropriate (pcase-defmacro * ...) you could definitely make it work. Not sure how useful it would be, but I'd have no problem with it: just like `append` it doesn't impact the rest of `pcase` (and I presume that it would come with a "predictably costly" complexity). Stefan From debbugs-submit-bounces@debbugs.gnu.org Wed Sep 02 04:39:08 2020 Received: (at 43100) by debbugs.gnu.org; 2 Sep 2020 08:39:08 +0000 Received: from localhost ([127.0.0.1]:58245 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kDOIN-0005On-HF for submit@debbugs.gnu.org; Wed, 02 Sep 2020 04:39:08 -0400 Received: from mail-oo1-f45.google.com ([209.85.161.45]:38681) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kDOIK-0005OH-P0 for 43100@debbugs.gnu.org; Wed, 02 Sep 2020 04:39:05 -0400 Received: by mail-oo1-f45.google.com with SMTP id z11so974069oon.5 for <43100@debbugs.gnu.org>; Wed, 02 Sep 2020 01:39:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=b470FM/TBZoOmtwxQOTr4Sv5vX3xvvw1o/uOBk+MqDY=; b=Xc8vsFJApCe4Z4R3xM22kFvceS3PDjozl5Z6YXppvjS0zJVOsaEg3Isjuq8AM8EzUd S0ufSvpZWNcMXZ/KhD9ctcSbxtx42GSWtvUfbdSMExi8KDFKTm21NtqWF8Hs5s0mpmxR dm5jDnL0qP4kHlBEFFkTe2KpS7B+0Kxkg/ehtpDNnRc6hayIVCyGHUM79OSrE+N21SEB q4bQiWntp0g3gUbasSvEZ7oqkYUhUt+WhI0YjG5Sr9WU6Ch7JLxdNWtH7uJSYuQsB1VG 33r2GwM7w5pWOn7ZSuOzfJ+RF8Oq6ktOE/gykODwe8+Z8dq5aiE4DhxSaPknVp9ICHq3 j1gQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=b470FM/TBZoOmtwxQOTr4Sv5vX3xvvw1o/uOBk+MqDY=; b=fqXUC+FfU4rgscBbvXYv3IW83++9lMDKh6CwkNbxcVcJMrhthp1sscLNRKacgGIGeO aP6qqhRI2CTkiRBTBDB99A4w0BklW5/o1oIXkbTV41ooSaOSz2zqhyGoFGeKdWsb7c8r c7k1pvAmSlAr1B0gaUzkSPjDkamzfq4V5FZ8QCMviqIRjGvroU/MXVe/q6fInc/+CCw0 UiBJ+uYeIFaXkYv5Sbna6UqJ85i7h7b5hEOA9lFTIb8/PiBbxxYzDwWg5NDdtDoTEalf uBQLS65XAZagF+2tJ6QjlQidDIZHVndK11G7PX3cVTswwqZQpRwN77Nxanh5zdwiLdDO s7mA== X-Gm-Message-State: AOAM5312FgcdX+kcrhvvlZ2OYWY8yK/6gu2cyqG7ODJdi6RgxhgUhhIc /4gi+lbYo1+mWUeQ5ebUDptT7gWY2Gz7oLrlhPA= X-Google-Smtp-Source: ABdhPJyJzo3fdjuArdVP8I+XYafYsJBKdIfYdH0ix98wvlwArDsIsJqOR6VyGebcVNoKmHoVAT1cA4Ru6HRdMoZXiPM= X-Received: by 2002:a4a:5a06:: with SMTP id v6mr4645821ooa.22.1599035938733; Wed, 02 Sep 2020 01:38:58 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Pip Cet Date: Wed, 2 Sep 2020 08:38:22 +0000 Message-ID: Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally To: Stefan Monnier Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 43100 Cc: Philipp Stephani , 43100@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On Tue, Sep 1, 2020 at 3:12 AM Stefan Monnier wr= ote: > > So, as I half-expected, the reaction to "pcase isn't powerful enough" > > is "let's make it less powerful" :-) > Your words, not mine. I'm glad you said that! > BTW, you can get (more or less) the behavior you want with: > > (pcase V > ((or (and (pred symbolp) (let name name)) name) > (let ((foo 'bar)) name))) That's a good alternative. > [ The "more or less" is because when V is a symbol, the `name` within > the body of the branch will not refer to the presumed surrounding > binding of `name` but to a new binding also called `name` which > temporarily hides the outer binding but is initialized to the same > value. The difference only kicks in if one of those bindings is > mutated. ] > > > Seriously, I get the impression you strongly feel pcase shouldn't be > > (more) powerful, it should instead make non-explicit but fairly strong > > complexity promises. > > I just want the complexity to be predictable without having to guess > which optimization will be applicable. So it's better to have a predictably-bad `append' rather than a sometimes-bad one? But how does that affect ,@? We could make that predictably bad, too! > >> More specifically, I'd rather not choose a semantics that imposes > >> duplicating the branch body, since we have no control over its size an= d > >> that can hence lead to potential code size explosion. > > You're right, and it's a good thing that the duplication of the branch > > body is a fixable implementation detail rather than something imposed > > by the semantics. > > It's only fixable if you disregard the "more or less" above. > I find it to be a pretty bad wrinkle in the semantics. So setq the outer binding if it changed? Note that people also might expect (pcase l (`(,a . ,b) (setq b a))) to modify l... > >> The design of `pcase` assumes you want to optimize away the tests that > >> are common to the various patterns. That can't be done with dynamic > >> patterns. > > Or it's a bit more difficult, at least... > I think it's more than "a bit more difficult", because deciding how to > optimize the tests will almost always take significantly more time than > just doing the tests. So in order to do it dynamically and be useful, > you still need to have 2 stages, where you optimize at one stage and > then use the result several times later (to recoup the cost of the > optimization). Wait, I think there was a misunderstanding here. I don't mean that the pcase pattern should depend structurally on let-bound variables appearing in it. That does sound impossible to me (except with dynamic scoping). > > The difficult part, in fact, is deciding that we want the arglist to > > be part of the exposed function API: given an "arglist" function, the > > rest of the implementation seems unproblematic, > > We have `help-function-arglist`, so it's not that hard. > But it's not guaranteed to work. Oh, thanks for pointing that out. It's not very good, though, is it? > > though some workarounds for lexical binding are required (if nothing > > else, this is an interesting exercise in how painful lexical binding > > can be to work with). > > It's more of a philosophical issue. Deciding whether to expose arglists for functions is, yes. That's what I said above. > Lexical scoping fundamentally means > that variables don't have names: (lambda (x) x) and (lambda (y) y) > should be indistinguishable (that's what =CE=B1-renaming says, anyway). But they're not. (equal (lambda (x) x) (lambda (y) y)) returns nil. I don't see why pcase-call should be in the "funcall" category of being unable to distinguish the two, rather than in the "equal" category of being able to. > >> So it's more like my option of returning nil, except it would return > >> the value of a surrounding `name` variable? That could be done, but I= 'm > >> not convinced it'd be more often useful. > > > > I started out with a fairly explicit practical problem: parsing GCC > > machine descriptions, which are (essentially) sexps but have made the > > mistake of having "optional" non-final parts, and I think it would be > > great to express that in a pcase pattern, both for the obvious reasons > > of legibility and for some non-obvious reasons of my own. > > I'm sorry, I don't understand what those sexps (and their =C2=ABoptional" > non-final parts=C2=BB) have to do with pcase's handling of `or` patterns > where the different branches don't bind the same set of variables. Well, maybe I'm just missing an obvious way of doing it. > >> > disallowing the modification of name in X. > >> That's rather hard to do (and I don't see what would be the benefit he= re). > > I meant adding a cautionary note about it in the documentation, not > > actively preventing it. > > So we're replacing the current "don't do that" with another "don't do > that", neither of which is detected by the byte-compiler? Yes. Emacs Lisp isn't free of "don't do that"s, and reducing the "don't do that" space drastically is better than pointing out the tiny fraction of it which remains as evidence that we shouldn't do the reduction in the first place. > I'd rather fix it "right" with something with a clean and > simple semantics where the things you shouldn't do get properly flagged > during compilation. If you want clean and simple (lexical scoping) semantics and execute user-provided code, you should probably call a user-provided lambda rather than evaluating an expression in the first place? > >> The current implementation amounts to "we should signal an error but w= e > >> don't bother doing so and just warn against it in the manual". > >> Patch welcome ;-) > > You mean a patch that would make pcase less powerful by making what I > > want to do impossible rather than merely difficult? > > The way I see it, it would make what you want to do possible because > what you suggest would merely give meaning to programs previously invalid= . > In contrast, with the current behavior your proposal implies breaking > backward compatibility. I think what you mean is you'd rather break backward compatibility in two steps rather than one, by first causing errors, then redefining the new errors not to happen? Because if so, I totally agree. > >> >> I don't know of a simple implementation. > >> > Here's my better-than-nothing attempt. I don't think that's complex= ; > >> > if anything, it's too trivial. > >> So you give it a search-based semantics. > > I don't think the semantics are at all unclear, > > You misunderstood: I definitely didn't mean "unclear" when wrote "search-= based". > The semantics are definitely clear. Saying I give it search-based semantics implies there are other semantics I could have chosen. Semantically, all I've done is decide, probably incorrectly, that append should be biased towards shy matching of the fist arguments (and that it only work on proper lists). > >> The problem with it for me is that if we turn > >> > >> `(,a ,@b) > >> > >> into > >> > >> (append `(,a) b) > > > > List-final ,@ is too special, IMHO, to be turned into an (append) > > pattern at all. > > So you want some ,@ to be turned into `append` and some not? As an implementation detail, yes. Just like ` does, by the way: `(,@l) doesn't call `append' (it doesn't even check l is a list!), so why should it behave differently when used as a pcase pattern? IOW, I'd like ` (as a pcase macro) to behave like ` already does: constant-time `(,@l), linear-time `(,@l 3). > That's exactly what I don't want, since it makes the performance > unpredictable unless you know the details of the optimization. I'm not opposed to the idea that there should be a form that means "use pcase to evaluate this, but throw an error if I messed up and complexity is worse than O(f(n))". I just don't think it should be (pcase ...), leaving the f to be determined by a human who's allowed to know the expected complexity of pcase patterns (currently not mentioned in the documentation), but isn't allowed to "know the details of the optimization". And, again, performance of ` is unpredictable unless you know the details of the optimization. Should we get rid of ` next? > >> the pcase match will take a lot more time than the equivalent > >> `(,a . ,b) > >> Of course, you can try and handle these "easy" cases more efficiently, > >> but then your ,@ will sometimes be very cheap and sometimes very > >> expensive (depending on when an optimization can be applied), which > >> I think is a misfeature (it's for this same reason that I dislike CL > >> keyword arguments for functions). > > I think it's an implementation detail. > > I don't want implementation details to choose between O(N) and O(1). > This is the kind of "detail" that should be chosen by the author. All powerful matching patterns I'm aware of have horrible worst-time complexity which is reduced to acceptable complexity for most cases, in practice. Take `equal', for example. (let (r s) (dotimes (i 100) (setq r (cons r r)) (setq s (cons s s)) (benchmark 1 `(equal ',r ',s)))) What you're asking sounds to me like the equivalent of "I want a compression algorithm to be as good as possible, but the size of the decompressed data has to be predictable, even if I perform recursive decompression of the output". > > Some reasoning about the minimum and maximum length of sequences > > matched by pcase patterns could help ordinary pcases, too, though: > > Potentially, of course. There are many options when it comes to the > actual code generated by `pcase`. Precisely, including ones that reduce complexity. Somewhat unpredictably. Which is why predictable performance is a bad thing to demand of pcase patterns. > > (pcase '(a b c d) > > (`(,a ,b ,c ,d) (list a b c d))) > > > > could call (pcase--check-length EXPVAL 4 4) rather than calling consp > > four times, potentially descending into expensive predicates that are > > unnecessary. > > But that presumes a C implementation of `pcase--check-length` since > (< (length X) 4) can be a very bad idea when X is a long list. Even a Lisp implementation that isn't a wrapper around (length X) would avoid unnecessary predicates. That is the reason I wrote pcase--check-length rather than (<=3D 4 (length EXPVAL) 4)... > > It's strange to read quotes that yo > ...? Well, it's strange to read quotes that you only half-deleted from your email, Pip! (Sorry). > > Again, I think that's a fundamental difference between us when it > > comes to the philosophy behind pcase. If I understand you correctly, > > you deliberately want to limit pcase, moving away from the intuitive > > definition of it that I gave above, because there might be a situation > > in which people expect better performance than our limited > > implementation can give them. Is that correct? > > [ The intuitive definition you gave doesn't work for most of the core > patterns in `pcase` (e.g. `pred`, `app`, `let`, `guard`), so while > it's fine as a guiding intuition, it can't be used to really define > the intended semantics. ] You mean because "pred" isn't defined as a function, and "let" is defined differently? Because if I'm allowed to defmacro pred, it works perfectly well: (defmacro pred (p) ``(pred ,p)) (defun equalish (a b) (... (pcase a (`(pred ,p) (funcall p b))) with extra hygiene being required, of course, but there's no problem here. > No, the problem is not really one of performance, but rather one of > defining which variables are in scope within a branch such that a given > branch always has the same set of bindings within its scope, no matter > how the pattern was matched, which I think gives it a cleaner and > simpler semantics. Yes: calling lambdas gives cleaner and simpler semantics than evaluating forms, which gives terser code and implies precisely the unclean (but useful) semantics I want. pcase does the latter, implying semantics which we can implement (more easily and cleanly using dynamic bindings, for some reason), but choose not to. I'd like to understand why! > [ It is also linked to a potential problem of code size explosion, > admittedly. ] Let's be clear, though, that we're not talking about an explosion in the number of conses used to express the pcase. It's only when the code is byte compiled that an explosion potentially happens (and it's easily fixable with dynamic binding, but not with lexical binding, as far as I can see). (I think it's interesting that you can't evaluate "proper" pcase at run time; at least, I don't see how you'd implement a pcase-dyn function that evaluates its second argument etc. before interpreting it. It's easy to do with dynamic binding. I think that's because our implementation of lexical binding is too limited, but I'm not sure.) > > I think that's a weak reason for a strong limitation, but of course > > those are subjective questions. > > I don't see what strong limitation you're referring to. Having `name` > get the value of a surrounding `name` instead of nil seems like a very > minor issue and definitely not a "strong limitation". The strong limitation is "you can only add new pcase patterns if they have predictable complexity (in code size, run time, or memory usage, presumably)". Taken at face value, that means no ,@, nothing equal-based, no efficient joining of two pcase cases into one... and no conditional binding of variables. (IMHO, (pcase X (A B) (C D)) should be equivalent to (pcase X ((or (and (let which-alternative 0) A) (and (let which-alternative 1) C)) (case which-alternative (0 B) (1 D)))), assuming "which-alternative" is free in A, B, C, D.) You're right, though, that it'll usually be possible to get the right behavior using the "bind everything to nil" idea. I hadn't understood you to be seriously proposing we implement that, but if you do I'll prepare a patch. > > For example, I don't expect (pcase 9 ((* x x) x)) to work, > > With an appropriate (pcase-defmacro * ...) you could definitely make it > work. By solving polynomial roots? I think it's better to use (pcase-defmacro * ...) for a Kleene star macro...which it turns out isn't precisely trivial to implement with lexical scoping. Pip From debbugs-submit-bounces@debbugs.gnu.org Wed Sep 02 10:17:04 2020 Received: (at 43100) by debbugs.gnu.org; 2 Sep 2020 14:17:04 +0000 Received: from localhost ([127.0.0.1]:60247 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kDTZP-0007vL-J7 for submit@debbugs.gnu.org; Wed, 02 Sep 2020 10:17:04 -0400 Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:4434) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kDTZN-0007uh-9y for 43100@debbugs.gnu.org; Wed, 02 Sep 2020 10:17:02 -0400 Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id B96B68009D; Wed, 2 Sep 2020 10:16:55 -0400 (EDT) Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 8D2EC80712; Wed, 2 Sep 2020 10:16:53 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1599056213; bh=UvscrvNNuDHuYwcxzOEIPHrr5Ynjvy41LAk4H+SpEkU=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From; b=R6EJ6UmfY8oornU/E7pISCOGy1uJO6F4dxZNgVXvHVTRzT/OvY0FaFmBv4oJ3XGoH p2mFlGQMu3lOZQ6S0s5x1kGBomdor5R7lqUfNTQHVmtHpM0aiXyF0i/dr43bkUDQ+G UxafZi2oLvoCVOA9XAoa7H6bcfrPrl4Yr8WsvMWSbLp5WbiW5EAD51lDN7b0jT80Td urDr0KvJ+Frs/gRfPYuT27PA+KLe8Ee99/+3H/FU9Rbk7Gt/jmESbAVG8JjNjLAjlc fPtwySiheCa3SilPdlRb+s3d+MrecS5pFev1Wjn7k5UJIs69mC1pv2AYLa904bn0Kz KemKCYMjSESCA== Received: from alfajor (unknown [45.72.232.131]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 5CF6112025D; Wed, 2 Sep 2020 10:16:53 -0400 (EDT) From: Stefan Monnier To: Pip Cet Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally Message-ID: References: Date: Wed, 02 Sep 2020 10:16:52 -0400 In-Reply-To: (Pip Cet's message of "Wed, 2 Sep 2020 08:38:22 +0000") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-SPAM-INFO: Spam detection results: 0 ALL_TRUSTED -1 Passed through trusted hosts only via SMTP AWL -0.061 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain X-SPAM-LEVEL: X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 43100 Cc: Philipp Stephani , 43100@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) >> I just want the complexity to be predictable without having to guess >> which optimization will be applicable. > So it's better to have a predictably-bad `append' rather than a > sometimes-bad one? In my book, yes. > But how does that affect ,@? We could make that predictably bad, too! I think the expectation (coming from the use of ,@ in non-patterns) would be that it is fairly cheap, but yes, I guess it's an option. Could be coupled with a warning when ,@ can be replaced by an efficient `. ,`. >> >> More specifically, I'd rather not choose a semantics that imposes >> >> duplicating the branch body, since we have no control over its size a= nd >> >> that can hence lead to potential code size explosion. >> > You're right, and it's a good thing that the duplication of the branch >> > body is a fixable implementation detail rather than something imposed >> > by the semantics. >> It's only fixable if you disregard the "more or less" above. >> I find it to be a pretty bad wrinkle in the semantics. > So setq the outer binding if it changed? Oh, yuck! That'd be adding injury to insult. > Note that people also might expect > > (pcase l (`(,a . ,b) (setq b a))) > > to modify l... They might indeed. But if so, they'll be disappointed ;-) >> >> The design of `pcase` assumes you want to optimize away the tests that >> >> are common to the various patterns. That can't be done with dynamic >> >> patterns. >> > Or it's a bit more difficult, at least... >> I think it's more than "a bit more difficult", because deciding how to >> optimize the tests will almost always take significantly more time than >> just doing the tests. So in order to do it dynamically and be useful, >> you still need to have 2 stages, where you optimize at one stage and >> then use the result several times later (to recoup the cost of the >> optimization). > Wait, I think there was a misunderstanding here. I don't mean that the > pcase pattern should depend structurally on let-bound variables > appearing in it. That does sound impossible to me (except with dynamic > scoping). To me "dynamic patterns" means patterns which are only know at run time because the pattern itself depends on a runtime value, as in something like: (let ((pat (if FOO '(pred symbolp) '1))) ... (pcase V ... ((match pat) EXP) ...)) Not sure what you meant by it, then. >> > The difficult part, in fact, is deciding that we want the arglist to >> > be part of the exposed function API: given an "arglist" function, the >> > rest of the implementation seems unproblematic, >> We have `help-function-arglist`, so it's not that hard. >> But it's not guaranteed to work. > Oh, thanks for pointing that out. It's not very good, though, is it? It's good enough for `C-h o`. >> Lexical scoping fundamentally means that variables don't have names: >> (lambda (x) x) and (lambda (y) y) should be indistinguishable (that's >> what =CE=B1-renaming says, anyway). > But they're not. ;-) > I don't see why pcase-call should be in the "funcall" category of > being unable to distinguish the two, rather than in the "equal" > category of being able to. The notion of equality between functions is pretty delicate (and this fundamental problem was the original motivation for the development of type classes, BTW). >> I'm sorry, I don't understand what those sexps (and their =C2=ABoptional" >> non-final parts=C2=BB) have to do with pcase's handling of `or` patterns >> where the different branches don't bind the same set of variables. > Well, maybe I'm just missing an obvious way of doing it. Could be, but I have no idea what "it" is. >> >> > disallowing the modification of name in X. >> >> That's rather hard to do (and I don't see what would be the benefit h= ere). >> > I meant adding a cautionary note about it in the documentation, not >> > actively preventing it. >> So we're replacing the current "don't do that" with another "don't do >> that", neither of which is detected by the byte-compiler? > Yes. Emacs Lisp isn't free of "don't do that"s, and reducing the > "don't do that" space drastically is better than pointing out the tiny > fraction of it which remains as evidence that we shouldn't do the > reduction in the first place. I don't see your proposal as reducing the "don't do that" space. >> >> The current implementation amounts to "we should signal an error but = we >> >> don't bother doing so and just warn against it in the manual". >> >> Patch welcome ;-) >> > You mean a patch that would make pcase less powerful by making what I >> > want to do impossible rather than merely difficult? >> The way I see it, it would make what you want to do possible because >> what you suggest would merely give meaning to programs previously invali= d. >> In contrast, with the current behavior your proposal implies breaking >> backward compatibility. > I think what you mean is you'd rather break backward compatibility in > two steps rather than one, by first causing errors, then redefining > the new errors not to happen? Because if so, I totally agree. That's right. The first (breaking) step would be "my fault" and would hence free you to do the second step without introducing incompatibilities ;-) > IOW, I'd like ` (as a pcase macro) to behave like ` already does: > constant-time `(,@l), linear-time `(,@l 3). I suggest you start with a `pip-backquote` pcase-macro and experiment with it, to see how useful it is. You'll then presumably have more concrete examples to argue for the replacement of the current `=20 > And, again, performance of ` is unpredictable unless you know the > details of the optimization. Should we get rid of ` next? AFAIK performance is O(N) where N is the number of cons cells in the output (minus those cons-cells which are preserved as-is, I guess but that doesn't make much of a difference). That seems quite different from going from O(1) to O(N=C2=B2). >> But that presumes a C implementation of `pcase--check-length` since >> (< (length X) 4) can be a very bad idea when X is a long list. > Even a Lisp implementation that isn't a wrapper around (length X) > would avoid unnecessary predicates. Indeed. I won't be the one writing the code which tries to guess when that's more efficient and when it's less efficient. >> > It's strange to read quotes that yo >> ...? > Well, it's strange to read quotes that you only half-deleted from your > email, Pip! (Sorry). ;-) > (I think it's interesting that you can't evaluate "proper" pcase at > run time; at least, I don't see how you'd implement a pcase-dyn > function that evaluates its second argument etc. before interpreting > it. It's easy to do with dynamic binding. I think that's because our > implementation of lexical binding is too limited, but I'm not sure.) I don't understand what your `pcase-dyn` would be expected to do, so I don't know how dynamic scoping might coming into the picture. > The strong limitation is "you can only add new pcase patterns if they > have predictable complexity (in code size, run time, or memory usage, > presumably)". Not at all. You can define any pcase pattern you like with `pcase-defmacro`, just like you can define any function or macro you like with `defun` and `defmacro`. > By solving polynomial roots? I think it's better to use > (pcase-defmacro * ...) for a Kleene star macro...which it turns out > isn't precisely trivial to implement with lexical scoping. Why would lexical scoping make a difference? Stefan From debbugs-submit-bounces@debbugs.gnu.org Sat Sep 05 10:37:36 2020 Received: (at 43100) by debbugs.gnu.org; 5 Sep 2020 14:37:36 +0000 Received: from localhost ([127.0.0.1]:43762 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kEZJv-0007KZ-M9 for submit@debbugs.gnu.org; Sat, 05 Sep 2020 10:37:36 -0400 Received: from mail-ot1-f46.google.com ([209.85.210.46]:46996) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kEZJu-0007KN-16 for 43100@debbugs.gnu.org; Sat, 05 Sep 2020 10:37:34 -0400 Received: by mail-ot1-f46.google.com with SMTP id c10so8507930otm.13 for <43100@debbugs.gnu.org>; Sat, 05 Sep 2020 07:37:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=KoEvJTaciOlZwHYJzLNJXGVXlns5fQWePGI51mywaSA=; b=Jvjzq3yowCP7n3GhqDNvTZkjcAPrBaGzAFRjeiBFiSIaiCAuN8iCZwEmZyJMXbtO3G OoA7nDyeyFgYpijM+jp5UmDKC519zxcA/GCVQIssqkj9uLUkqOisGZ60FaoGYlt6xCzc SzH5ZS0ZPYnBrq8zXp31iqZVf7VlaH6kAuZ4YdzdWln2LY18bt8xmaaVo38QtkWeN7nQ 23dHF+Q8ziT6Aco4hF1zPyxynJLwFG4f5szhL+e4vwLtvca3cIGxDOUgWZP78jd1Czpp IcU/OAFggGTh7cRpVVHFtNs+Bs6RXEiQNa8kkgUUwqqjFwU7KBvHTAH+pKDo/91hxwhI wKyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=KoEvJTaciOlZwHYJzLNJXGVXlns5fQWePGI51mywaSA=; b=jG6es6tj9xYlatVUOQiLdV7k4q7CnQ8PvCDdedf25CqR7nqLhrgvXxSnGKqQbXhFte V+ofk4NmqCadb3+ejxekGkSNEFeukj+iCHEsffsymHuOEWuh2lqZYEtpR/qMeKA/Q7kL LjteoRr7QZ5vX/9tP8yCaQcbrm7YruMflzcFS0/7YXZl/kxcLUyueizP/RGO/8/kSRoO e2WCpPdF/XD4Rex+3Br/Wiw31hoc1PKEItEFPh2SAgA1QqoMVB7Hr+R70fpAGYNNdgwp ZHLo+ldwhq7dIgr+JYU/2L1Ds1+XeBfN0SgZvCVwCC2tnWxUR1EDX1li27oIqUMnkfTx x9wA== X-Gm-Message-State: AOAM532gD3BgX7PsVTRYMY7LsN+7J/Mb31wIG8zwtq5BAdPzbdhSWf2q vYfWnt0IGHmUa/o8auA5AsDAJeiMCEsQUMNMi4c= X-Google-Smtp-Source: ABdhPJyOtGkAh0NCWm0bViwZ1tHL3IrfP9NejaEig7Z3/lGWlkBMKOjQ6k/N6h1fQqUYnF/NiYRgSONhnj0sJYxp8Wo= X-Received: by 2002:a9d:2c43:: with SMTP id f61mr9754529otb.154.1599316648114; Sat, 05 Sep 2020 07:37:28 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Pip Cet Date: Sat, 5 Sep 2020 14:36:50 +0000 Message-ID: Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally To: Stefan Monnier Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 43100 Cc: Philipp Stephani , 43100@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On Wed, Sep 2, 2020 at 2:16 PM Stefan Monnier wr= ote: > >> I just want the complexity to be predictable without having to guess > >> which optimization will be applicable. > > So it's better to have a predictably-bad `append' rather than a > > sometimes-bad one? > In my book, yes. That's a very unusual book! This isn't real-time programming or crypto, so I fail to see the damage "faster is better" might cause here. > > But how does that affect ,@? We could make that predictably bad, too! > > I think the expectation (coming from the use of ,@ in non-patterns) > would be that it is fairly cheap, but yes, I guess it's an option. > Could be coupled with a warning when ,@ can be replaced by an efficient > `. ,`. I don't think we should warn about that; we should simply do the best we can do, and warn the user when that's surprisingly bad (i.e. when we have to iterate over the list building sublists). > >> >> More specifically, I'd rather not choose a semantics that imposes > >> >> duplicating the branch body, since we have no control over its size= and > >> >> that can hence lead to potential code size explosion. > >> > You're right, and it's a good thing that the duplication of the bran= ch > >> > body is a fixable implementation detail rather than something impose= d > >> > by the semantics. > >> It's only fixable if you disregard the "more or less" above. > >> I find it to be a pretty bad wrinkle in the semantics. > > So setq the outer binding if it changed? > Oh, yuck! That'd be adding injury to insult. Would work, though! > >> >> The design of `pcase` assumes you want to optimize away the tests t= hat > >> >> are common to the various patterns. That can't be done with dynami= c > >> >> patterns. > >> > Or it's a bit more difficult, at least... > >> I think it's more than "a bit more difficult", because deciding how to > >> optimize the tests will almost always take significantly more time tha= n > >> just doing the tests. So in order to do it dynamically and be useful, > >> you still need to have 2 stages, where you optimize at one stage and > >> then use the result several times later (to recoup the cost of the > >> optimization). > > Wait, I think there was a misunderstanding here. I don't mean that the > > pcase pattern should depend structurally on let-bound variables > > appearing in it. That does sound impossible to me (except with dynamic > > scoping). > > To me "dynamic patterns" means patterns which are only know at run time > because the pattern itself depends on a runtime value, as in something li= ke: > > (let ((pat (if FOO '(pred symbolp) '1))) > ... > (pcase V > ... > ((match pat) EXP) > ...)) > > Not sure what you meant by it, then. I didn't mean anything by "dynamic patterns" because I didn't use the term = :-) What I meant was using SYMBOL as short-hand for (pred (equal SYMBOL)) when it's not in a white-list of symbols to be bound instead of compared. That was the intention of my example. I think dynamic patterns, as you use the term, should be possible (IIUC, they're not, with lexical binding), but punitively slow (I don't think we have to worry about that last part...), but that's an entirely different discussion. > >> We have `help-function-arglist`, so it's not that hard. > >> But it's not guaranteed to work. > > Oh, thanks for pointing that out. It's not very good, though, is it? > > It's good enough for `C-h o`. C-h o says (+ &rest NUMBERS-OR-MARKERS) and (1+ NUMBER) help-function-arglist says (&rest rest) and (arg1) The latter is much less useful, IMHO. > >> I'm sorry, I don't understand what those sexps (and their =C2=ABoption= al" > >> non-final parts=C2=BB) have to do with pcase's handling of `or` patter= ns > >> where the different branches don't bind the same set of variables. > > Well, maybe I'm just missing an obvious way of doing it. > Could be, but I have no idea what "it" is. Matching something like Emacs defuns, which may have a docstring or not, I'd like to do `(defun ,symbol ,@(or `(,(and (pred stringp) docstring))) `()) . ,body) It seems wasteful to have two almost-identical patterns to match the variants, and I'd like docstring to have a useful default value. > >> >> > disallowing the modification of name in X. > >> >> That's rather hard to do (and I don't see what would be the benefit= here). > >> > I meant adding a cautionary note about it in the documentation, not > >> > actively preventing it. > >> So we're replacing the current "don't do that" with another "don't do > >> that", neither of which is detected by the byte-compiler? > > Yes. Emacs Lisp isn't free of "don't do that"s, and reducing the > > "don't do that" space drastically is better than pointing out the tiny > > fraction of it which remains as evidence that we shouldn't do the > > reduction in the first place. > > I don't see your proposal as reducing the "don't do that" space. Currently, it's "don't bind variables only in some branches of a pcase or". With my proposal, it's "feel free to bind variables only in some branches of a pcase or, but don't modify them". It's a strict subset relationship. > >> >> The current implementation amounts to "we should signal an error bu= t we > >> >> don't bother doing so and just warn against it in the manual". > >> >> Patch welcome ;-) > >> > You mean a patch that would make pcase less powerful by making what = I > >> > want to do impossible rather than merely difficult? > >> The way I see it, it would make what you want to do possible because > >> what you suggest would merely give meaning to programs previously inva= lid. > >> In contrast, with the current behavior your proposal implies breaking > >> backward compatibility. > > I think what you mean is you'd rather break backward compatibility in > > two steps rather than one, by first causing errors, then redefining > > the new errors not to happen? Because if so, I totally agree. > > That's right. The first (breaking) step would be "my fault" and would > hence free you to do the second step without introducing > incompatibilities ;-) Hooray! Let's do that, then. > > IOW, I'd like ` (as a pcase macro) to behave like ` already does: > > constant-time `(,@l), linear-time `(,@l 3). > > I suggest you start with a `pip-backquote` pcase-macro and experiment > with it, to see how useful it is. You'll then presumably have more > concrete examples to argue for the replacement of the current ` > > > And, again, performance of ` is unpredictable unless you know the > > details of the optimization. Should we get rid of ` next? > AFAIK performance is O(N) where N is the number of cons cells in the > output (minus those cons-cells which are preserved as-is, I guess but > that doesn't make much of a difference). It means (,@l) is O(1), but (,@l 3) is O(N). > That seems quite different > from going from O(1) to O(N=C2=B2). So going from O(1) to O(N) is okay, but O(N^2) is not? I think it would be okay to throw a "use append!" warning, or even an error, if we encounter a situation in which there is more than one ,@ without a maximum length (i.e. situations in which we fail to be O(N), given constant-time predicates). > >> But that presumes a C implementation of `pcase--check-length` since > >> (< (length X) 4) can be a very bad idea when X is a long list. > > Even a Lisp implementation that isn't a wrapper around (length X) > > would avoid unnecessary predicates. > > Indeed. I won't be the one writing the code which tries to guess when > that's more efficient and when it's less efficient. Hmm. After running some benchmarks, it seems like a C implementation of check-length is slightly faster, a Lisp implementation of check-length is slightly slower, there's less code (in terms of cons cells) generated with check-length, but the bytecode looks better without it. All that is without any predicates and in the case of a matching pattern, so I'd say it's a wash then. In theory, of course, it's easy to come up with an algorithm that uses both approaches to achieve minimum complexity, but that's difficult to implement. So my tentative proposal would be to use `append' or ,@ if you want length reasoning, plain ` and , if you don't. It might be simpler always to use it, but I don't want (pcase x (a b) (cons a b)) to emit a function call. > > (I think it's interesting that you can't evaluate "proper" pcase at > > run time; at least, I don't see how you'd implement a pcase-dyn > > function that evaluates its second argument etc. before interpreting > > it. It's easy to do with dynamic binding. I think that's because our > > implementation of lexical binding is too limited, but I'm not sure.) > > I don't understand what your `pcase-dyn` would be expected to do, so > I don't know how dynamic scoping might coming into the picture. It's what you called dynamic patterns above. The problem is you cannot eval a pcase form and achieve lexical binding of the variables used in the bindings. There's no lexical-scoping equivalent of (eval `(pcase ',exp ,bindings)) I expect you'll object that that's usually not what you want, anyway, which is correct but leaves the unusual cases where you know that the pcase will have been memoized and thus be fairly cheap. > > The strong limitation is "you can only add new pcase patterns if they > > have predictable complexity (in code size, run time, or memory usage, > > presumably)". > > Not at all. You can define any pcase pattern you like with > `pcase-defmacro`, just like you can define any function or macro you > like with `defun` and `defmacro`. Well, I wish :-) pcase-defmacro is limited to non-recursive patterns. Thanks for clarifying that the kingdom of predictable complexity does not extend to pcase-defmacro. > > By solving polynomial roots? I think it's better to use > > (pcase-defmacro * ...) for a Kleene star macro...which it turns out > > isn't precisely trivial to implement with lexical scoping. > > Why would lexical scoping make a difference? Because pcase patterns cannot be recursive (or can they?), but you can recurse, given dynamic scoping, by eval'ing a pcase form. By the way, I'm also quite confused by this comment: ;; - implement (not PAT). This might require a significant redesign. (pcase-defmacro not (pat) `(app (lambda (expval) (not (pcase expval (,pat t)))) (pred identity))) would work, wouldn't it? Or did I totally misunderstand what a pcase not would be expected to do? From debbugs-submit-bounces@debbugs.gnu.org Sat Sep 05 12:52:37 2020 Received: (at 43100) by debbugs.gnu.org; 5 Sep 2020 16:52:37 +0000 Received: from localhost ([127.0.0.1]:43976 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kEbQa-0006YS-VM for submit@debbugs.gnu.org; Sat, 05 Sep 2020 12:52:37 -0400 Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:16943) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kEbQY-0006YF-4f for 43100@debbugs.gnu.org; Sat, 05 Sep 2020 12:52:34 -0400 Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id E7466809C7; Sat, 5 Sep 2020 12:52:27 -0400 (EDT) Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 26FFF8092B; Sat, 5 Sep 2020 12:52:21 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1599324741; bh=qImv46PdyQzxzLkRgwuRfsK5i0oKZ8r50lJWHRRur5M=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From; b=iBfa7Omt3yxQv9xfmPxzLmjCL6ii4BOYqBWeR7hmDEp3QKFbvvpaXT6O3dfhpdkxa khXz8A3zBqWsQzHvEGajqBKTFnA7fATXI3kgklU57+zn2y2/MPxxgurIOG766DeiVG cm4dBXviZASk2dtxHJbqLT2zD0isBdnp3tjprTX/46TCh2VYOFLnQHGdGLSoKuV2xS ztigk7j8SundEO9yM7eyzKwm1JJmAphjny4xQmZPBlnZq4iXA0FxaVnVedCE4tIjkl PDcqtpTWQReVNemwWNapulED8iYcoNZAYZfEyId5QnUVxllq2NxuEO1XYCkHnh13Ax XScq2YIMqDlWA== Received: from alfajor (unknown [45.72.232.131]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id E77E9120604; Sat, 5 Sep 2020 12:52:20 -0400 (EDT) From: Stefan Monnier To: Pip Cet Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally Message-ID: References: Date: Sat, 05 Sep 2020 12:52:14 -0400 In-Reply-To: (Pip Cet's message of "Sat, 5 Sep 2020 14:36:50 +0000") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable X-SPAM-INFO: Spam detection results: 0 ALL_TRUSTED -1 Passed through trusted hosts only via SMTP AWL -0.062 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DKIM_SIGNED 0.1 Message has a DKIM or DK signature, not necessarily valid DKIM_VALID -0.1 Message has at least one valid DKIM or DK signature DKIM_VALID_AU -0.1 Message has a valid DKIM or DK signature from author's domain X-SPAM-LEVEL: X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 43100 Cc: Philipp Stephani , 43100@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) >> >> I just want the complexity to be predictable without having to guess >> >> which optimization will be applicable. >> > So it's better to have a predictably-bad `append' rather than a >> > sometimes-bad one? >> In my book, yes. > That's a very unusual book! I wouldn't know, it's the only one I have. > This isn't real-time programming or crypto, so I fail to see the > damage "faster is better" might cause here. Because the problem goes in the other direction: the programmer gets used to seeing it work fast on some uses and then assumes it's always so, and then gets bitten on other uses. I think a good API should avoid such surprises. [ This said, I no doubt introduced several APIs which don't obey this rule. But then I plead not guilty because of temporary insanity. ] >> > But how does that affect ,@? We could make that predictably bad, too! >> I think the expectation (coming from the use of ,@ in non-patterns) >> would be that it is fairly cheap, but yes, I guess it's an option. >> Could be coupled with a warning when ,@ can be replaced by an efficient >> `. ,`. > I don't think we should warn about that; we should simply do the best > we can do, and warn the user when that's surprisingly bad (i.e. when > we have to iterate over the list building sublists). It's important to try and make sure that warnings can be silenced by improving the code. When the coders really need the slow search, how would they silence the warning (other than `with-suppressed-warnings`, obviously)? In contrast if we warn when the ,@ can be replaced by `, .` then the warning can always be silenced without having to resort to `with-suppressed-warnings`. >> >> >> More specifically, I'd rather not choose a semantics that imposes >> >> >> duplicating the branch body, since we have no control over its siz= e and >> >> >> that can hence lead to potential code size explosion. >> >> > You're right, and it's a good thing that the duplication of the bra= nch >> >> > body is a fixable implementation detail rather than something impos= ed >> >> > by the semantics. >> >> It's only fixable if you disregard the "more or less" above. >> >> I find it to be a pretty bad wrinkle in the semantics. >> > So setq the outer binding if it changed? >> Oh, yuck! That'd be adding injury to insult. > Would work, though! And would result in hideous semantics in corner cases. > What I meant was using SYMBOL as short-hand for (pred (equal SYMBOL)) > when it's not in a white-list of symbols to be bound instead of > compared. That was the intention of my example. Ah, sorry, I completely misunderstood ;-) There's also a case to be made for SYMBOL to be an accepted short form for `(pred SYMBOL)` in some cases. I don't think using whitelists/blacklists to decide how to treat a given SYMBOL pattern will scale (nor be sufficiently clear for the casual reader), so I think we should aim for a slightly less concise syntax. Given the limits of the syn= tax accepted by the Elisp reader, we may have to resort to using (=3D EXP) as shorthand for (pred (equal EXP)) or =3DSYMBOL as shorthand for (pred (equal SYMBOL)) AFAIK There is currently no good hook in `pcase.el` to implement the latter without actually changing `pcase.el`. > I think dynamic patterns, as you use the term, should be possible They very much are possible, of course. E.g.: (defun pcase-match-p (PATTERN OBJECT) "Return non-nil if OBJECT matches PATTERN." (eval `(pcase ',OBJECT (,PATTERN t)) t)) and then use (pred (pcase-match-p EXP)) If you want to extract data from OBJECT, then you'll presumably want to define a `pcase-match` function which instead of a boolean returns a list of values (corresponding to the value of the variables that were bound in the PATTERN) and that will take more work than the above 3 lines, but should still be easy to do. > but punitively slow Yup. >> >> We have `help-function-arglist`, so it's not that hard. >> >> But it's not guaranteed to work. >> > Oh, thanks for pointing that out. It's not very good, though, is it? >> It's good enough for `C-h o`. > > C-h o says > > (+ &rest NUMBERS-OR-MARKERS) and (1+ NUMBER) Indeed and that info comes straight from `help-function-arglist`. > help-function-arglist says > > (&rest rest) and (arg1) I suggest you start with `C-h o help-function-arglist` ;-) >> >> I'm sorry, I don't understand what those sexps (and their =ABoptional" >> >> non-final parts=BB) have to do with pcase's handling of `or` patterns >> >> where the different branches don't bind the same set of variables. >> > Well, maybe I'm just missing an obvious way of doing it. >> Could be, but I have no idea what "it" is. > > Matching something like Emacs defuns, which may have a docstring or > not, I'd like to do > > `(defun ,symbol ,@(or `(,(and (pred stringp) docstring))) `()) . ,body) > > It seems wasteful to have two almost-identical patterns to match the > variants, and I'd like docstring to have a useful default value. Currently `pcase` should give nil as value to `docstring` if the above `or` matches via the second alternative, so at least the "useful default" part is already covered ;-) But yes, currently, you have to write it like `(defun ,symbol ,args . ,(or `(,(and (pred stringp) docstring) . ,body) body)) or if you want a more explicit default for `docstring`: `(defun ,symbol ,args . ,(or `(,(and (pred stringp) docstring) . ,body) (and (let docstring "") body))) In this particular case it's not too terrible, but it gets much worse if you have to add more optional stuff to it, like `declare` and `interactive` (the pattern's size is exponential in the number of optional elements). Your `append` handles it more elegantly in the source code (and less efficiently at run-time). In theory we could get our cake and eat it too, but that would involve adding something similar to a parsing algorithm and would likely require a significant amount of work. >> > And, again, performance of ` is unpredictable unless you know the >> > details of the optimization. Should we get rid of ` next? >> AFAIK performance is O(N) where N is the number of cons cells in the >> output (minus those cons-cells which are preserved as-is, I guess but >> that doesn't make much of a difference). > It means (,@l) is O(1), but (,@l 3) is O(N). Indeed. It's not as drastic as the O(1) of `. ,` vs O(N=B2) of `append`, but point taken. I think it's time you (pcase-defmacro pip-\` ...) and experiment with it. > By the way, I'm also quite confused by this comment: > > ;; - implement (not PAT). This might require a significant redesign. > > (pcase-defmacro not (pat) > `(app (lambda (expval) (not (pcase expval (,pat t)))) > (pred identity))) > > would work, wouldn't it? [ AKA (pcase-defmacro not (pat) `(pred (lambda (expval) (not (pcase expval (,pat t)))))) ] Yes, it works but it doesn't give me the efficiency and semantics that a "true" `not` pattern should give. If you look at Racket's `match` (from which I took a lot of inspiration in the Emacs-25 refresh of pcase), you'll see that their negation pattern is trivial to implement (it's basically just swapping the "things to do upon success" with the "things to do upon failure") but gives the right semantics and efficiency. E.g. `(not (not PAT))` behaves just like PAT (including variable bindings and such). Stefan From debbugs-submit-bounces@debbugs.gnu.org Tue Mar 02 08:38:44 2021 Received: (at 43100-done) by debbugs.gnu.org; 2 Mar 2021 13:38:44 +0000 Received: from localhost ([127.0.0.1]:52081 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lH5Ea-0000XV-Be for submit@debbugs.gnu.org; Tue, 02 Mar 2021 08:38:44 -0500 Received: from mail-oi1-f177.google.com ([209.85.167.177]:36686) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1lH5EZ-0000XI-0c for 43100-done@debbugs.gnu.org; Tue, 02 Mar 2021 08:38:43 -0500 Received: by mail-oi1-f177.google.com with SMTP id j1so21973529oiw.3 for <43100-done@debbugs.gnu.org>; Tue, 02 Mar 2021 05:38:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=qstACl9Ti6F2F3b7zwsagCg+KN2IiQTqL1DdZ4gcK20=; b=R1Tn/9Ke6WxTT+TqY4Iw13BiovhPt+2MBTyiiojp07HB6bb5h8kQsRv5gBwhDUlsTs FtnaEewA4MtAvVUJ3fGFmfgsqKqoRxClMsVPfB62gONvz5+fWPJAGB3rxLif/a6laCOk AIbzM8Z9xg7fVUxi/RbPMwwuTyl8Ukn34bKmyQWfhpiOK93YSWxujwSzrufuiySXUx8b I90h2D9e2JN6OAE9XceW8I5OpddTqLv4dJpj4zGJ7YqA6khAPd/5xs56lKeppG5QhLMm LzARNTFQPwXYVO/V0SoUknjwrfAKQcMIL3683qwlHQsWikDsG2Ys0ogHt3FjNGQIWM9X rg1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=qstACl9Ti6F2F3b7zwsagCg+KN2IiQTqL1DdZ4gcK20=; b=d4sKXbMWgZt4G2R7AfENuPGt8nxqk1UVny/IsUzsZiDs2wOr1nA90u8MUudqYXxAlA J6qR8YzbDdPJv2RlwXSahuioQ+kcQK5QfvImdTy6H7rXY8WcQuiPsfMGP4f9oWTJro1a BeTgp1xKmBqWOcqqJmkd/g0iekXdwQ5Jdjsw5Tl8S8I00EQP8octb8rIIzW5FWt2qvbK 6kYF10UHp5329U4/5vg+nnPBH4v70eA2lz6fJ5ZdS1Pm+fXOlONyawXq4ux4I/D6YZYx bG0+QULYijCQ4T+NmBKKxVUM1AQXxMe89cW86LoLtpI2gFiFMw7iMFPbzdM5PbGWhPXc cqaw== X-Gm-Message-State: AOAM530KKtjzWOnAFHeaiMkeYoebj6bVZ50E5i0onSZFXxKplOJeCAKs yhCY/JofCk48c2VqIGxrmGDsa3+7MZXkOZQE1EEWylUducUm3w== X-Google-Smtp-Source: ABdhPJz0NiZOsvI8MhQaCLaoR4lT+bIR2B/3yRd4BE8JWbz2eVFN7isCeVZICMV0QpsvVzbkxDdS8YEelhtnol4IEqM= X-Received: by 2002:aca:af0e:: with SMTP id y14mr606270oie.44.1614692317285; Tue, 02 Mar 2021 05:38:37 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Pip Cet Date: Tue, 2 Mar 2021 13:38:01 +0000 Message-ID: Subject: Re: bug#43100: 28.0.50; pcase not binding variables conditionally To: 43100-done@debbugs.gnu.org, Stefan Monnier Content-Type: text/plain; charset="UTF-8" X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 43100-done X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On Sat, Aug 29, 2020 at 9:42 AM Pip Cet wrote: > > I'm having trouble with pcase's behavior. > > (pcase "a" > ((or (pred symbolp) name) > (let ((foo 'bar)) name))) Stefan fixed this in 165353674e5fe7109ba9cbf526de0333902b7851, so I'm closing this bug. Pip From unknown Sat Jun 21 10:38:38 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Wed, 31 Mar 2021 11:24:04 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator