From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier via "Emacs development discussions." Newsgroups: gmane.emacs.devel Subject: Re: Code for cond* Date: Sat, 27 Jan 2024 23:16:28 -0500 Message-ID: References: Reply-To: Stefan Monnier Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="5298"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) To: emacs-devel@gnu.org Cancel-Lock: sha1:AW2p24cC3oAfcHw9zK48pQQZT2w= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Jan 28 05:17:41 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rTwc1-0001FS-8H for ged-emacs-devel@m.gmane-mx.org; Sun, 28 Jan 2024 05:17:41 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rTwbF-000839-Vm; Sat, 27 Jan 2024 23:16:55 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rTwb3-0007zc-Pf for emacs-devel@gnu.org; Sat, 27 Jan 2024 23:16:42 -0500 Original-Received: from ciao.gmane.io ([116.202.254.214]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rTwb1-0000D2-EM for emacs-devel@gnu.org; Sat, 27 Jan 2024 23:16:41 -0500 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1rTwaw-000APi-Pc for emacs-devel@gnu.org; Sun, 28 Jan 2024 05:16:34 +0100 X-Injected-Via-Gmane: http://gmane.org/ Received-SPF: pass client-ip=116.202.254.214; envelope-from=ged-emacs-devel@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.249, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:315520 Archived-At: Richard Stallman [2024-01-25 23:30:24] wrote: > [[[ To any NSA and FBI agents reading my email: please consider ]]] > [[[ whether defending the US Constitution against all enemies, ]]] > [[[ foreign or domestic, requires you to follow Snowden's example. ]]] > > > Finally, I see a fairly extensive but hardcoded pattern language, which > > seems like a regression compared to Pcase where the pattern language is > > built from a few primitives only (with the rest defined on top via > > `pcase-defmacro`). > > cond* also has a macro-like way to extend the patterns. Is this what you're referring to? ((get (car subpat) 'cond*-expander) ;; Treat result as a subpattern. (cond*-subpat (funcall (get (car subpat) 'cond*-expander) subpat) cdr-safe bindings backtrack-aliases data)) do we have reasons to believe that it's flexible enough? For `pcase`, I needed to add the `app` pattern before `pcase-defmacro` was actually usable for more realistic extensions. And to be sure it was flexible enough I restructured the code so that patterns like backquote are not hardcoded in Pcase but are implemented using this extension facility. But more importantly, I really fail to see why we can't just use Pcase patterns here (potentially with adjustments to Pcase)? Let's look at them one by one: CONSTANT: nil, t, a keyword, a quoted constant, VARIABLE: a symbol A backquoted cons cell (or SUBPATTERNS...) (and SUBPATTERNS...) (rx RX-PATTERN) these are identical to Pcase (well, maybe not 100%, since that depends on details of the implementation which I haven't been able to test yet, but to a large extent at least). MACRO-CALL: a list which is a call to a macro. I used that trick in `gv.el` for places and it served us well, but I'm wondering if it'll work as well here. Can you think of macros for which this will do something useful? If it's rarely useful, then we have to take into account the potential drawback of having "mysterious" behavior or errors when the programmer didn't expect this macro expansion. A vector Pcase currently doesn't support exactly this, but does support it within the backquote pattern, i.e. instead of [PAT1 PAT2 ...] you have to use `[,PAT1 ,PAT2 ...] and with the other difference that it only matches if the two vectors have the same length. I resisted the addition of a vector pattern because I didn't know which kinds of patterns would be most useful (e.g. in terms of how the length should be constrained, ...). We could add a pattern like the one you have in `match*` to Pcase, but the experience with Pcase suggests that patterns like that on vectors are *very* rarely use(d|ful), so I don't think it's worth the trouble. (cdr-safe BACKQUOTED-CONS-CELL) (cdr BACKQUOTED-CONS-CELL) These would be easy to add to Pcase, of course. A string In Pcase patterns, strings are considered to fall within the first case above, i.e. constants. We have `re-match` of course, when we need to match a regex against a string. Which one deserves the shorter syntax of "just a string" is debatable (of course, some readers may point out that the question would be moot if we had a special syntax for regexps). (rx RX-PATTERN VARS...) For some reason currently our `rx` doesn't have such an option, but it would be easy to add, AFAICT. A backquoted structure constructor We don't currently support hat in Pcase, but neither does your code, and Pcase could support it just as well. (PRED VARIABLE) or, more generally, We don't have that currently. Instead we have (pred PRED) and if you want to bind it to a var you need (and (pred PRED) VAR) Extending `pred` so it can bind the value to a variable is definitely an option. It's fairly often useful. That's one of the reasons why I was careful to limit `pred` to a single argument so far (so it has room to grow by giving some useful meaning to additional args based on experience). E.g. we could easily add support for (pred PRED VARIABLE) And of course we could also add support for your (PRED VARIABLE) syntax, although until now I've resisted the urge to eat up Pcase pattern's namespace this way. (PRED VARIABLE OTHER-ARGS...) Without the VARIABLE part, in Pcase this is almost the same as (pred (PRED OTHER-ARGS...)) except that in Pcase, the value is passed as the last argument rather as first argument. I haven't seen a strong reason to prefer one over the other. I've considered extending `pred` to support the use of `_` in OTHER-ARGS... in order to specify the argument position of the value. If we combine that with the above (pred PRED VAR) extension, then we could get the same behavior as (PRED VARIABLE OTHER-ARGS...) with (pred (PRED _ OTHER-ARGS...) VARIABLE) and finally: (constrain VAR EXPRESSION) This would be very easy to add. It's basically (and VAR (guard EXPRESSION)) and just as for `pred` there is evidence that it would be desirable to extend it so as to include the `and` behavior, so we could have (guard VAR EXPRESSION) IOW, while your patterns aren't 100% covered by current Pcase patterns, Pcase can easily accommodate them, and it would be a shame to introduce a second pattern language that's almost-identical-but-not-quite. Is there *any* reason why `cond*` needs a different pattern language? Stefan PS: Is the code available for testing somewhere? The code I have here (from Jan 19) doesn't work: ELISP> (cond* ((match* `(a ,y) '(a 5)) y)) *** Eval error *** Symbol’s value as variable is void: ba162 ELISP>