From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.bugs Subject: bug#43100: 28.0.50; pcase not binding variables conditionally Date: Wed, 02 Sep 2020 10:16:52 -0400 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="21676"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) Cc: Philipp Stephani , 43100@debbugs.gnu.org To: Pip Cet Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Sep 02 16:18:10 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kDTaU-0005TG-51 for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 02 Sep 2020 16:18:10 +0200 Original-Received: from localhost ([::1]:53286 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kDTaT-0005sd-6v for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 02 Sep 2020 10:18:09 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:57810) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kDTaM-0005s5-57 for bug-gnu-emacs@gnu.org; Wed, 02 Sep 2020 10:18:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:48707) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kDTaL-0000Lc-ND for bug-gnu-emacs@gnu.org; Wed, 02 Sep 2020 10:18:01 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1kDTaL-0007wz-J1 for bug-gnu-emacs@gnu.org; Wed, 02 Sep 2020 10:18:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 02 Sep 2020 14:18:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 43100 X-GNU-PR-Package: emacs Original-Received: via spool by 43100-submit@debbugs.gnu.org id=B43100.159905622430467 (code B ref 43100); Wed, 02 Sep 2020 14:18:01 +0000 Original-Received: (at 43100) by debbugs.gnu.org; 2 Sep 2020 14:17:04 +0000 Original-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 Original-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 Original-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) Original-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== Original-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) In-Reply-To: (Pip Cet's message of "Wed, 2 Sep 2020 08:38:22 +0000") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:186934 Archived-At: >> 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