From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Joost Kremers Newsgroups: gmane.emacs.devel Subject: Re: Replace trivial pcase occurrences in the Emacs sources Date: Wed, 24 Oct 2018 10:34:23 +0200 Message-ID: <20181024083423.GA13100@Swift> References: <87oad2irtd.fsf@fencepost.gnu.org> <5689456A.1010601@yandex.ru> <87egdy8tyz.fsf@fencepost.gnu.org> <56895FDE.4060406@yandex.ru> <8760za8r4a.fsf@fencepost.gnu.org> <87h9iunkcg.fsf@web.de> <87h8hc4xw2.fsf_-_@web.de> <83tvlcsnee.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Trace: blaine.gmane.org 1540371868 21453 195.159.176.226 (24 Oct 2018 09:04:28 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 24 Oct 2018 09:04:28 +0000 (UTC) User-Agent: Mutt/1.9.4 (2018-02-28) To: Richard Stallman Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Oct 24 11:04:24 2018 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gFF5T-0005Rx-Gi for ged-emacs-devel@m.gmane.org; Wed, 24 Oct 2018 11:04:23 +0200 Original-Received: from localhost ([::1]:46895 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gFF7a-0002bq-2h for ged-emacs-devel@m.gmane.org; Wed, 24 Oct 2018 05:06:34 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:58808) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gFF6s-0002af-DY for emacs-devel@gnu.org; Wed, 24 Oct 2018 05:05:51 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gFF6o-00089q-SO for emacs-devel@gnu.org; Wed, 24 Oct 2018 05:05:50 -0400 Original-Received: from out3-smtp.messagingengine.com ([66.111.4.27]:46985) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gFF6o-00089W-Lk for emacs-devel@gnu.org; Wed, 24 Oct 2018 05:05:46 -0400 Original-Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 54AAF21F23 for ; Wed, 24 Oct 2018 05:05:46 -0400 (EDT) Original-Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Wed, 24 Oct 2018 05:05:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fastmail.fm; h= resent-from:resent-date:resent-message-id:resent-to:date:from:to :subject:message-id:references:mime-version:content-type :content-transfer-encoding:in-reply-to; s=fm1; bh=GLYTDl3AlhEBhi AdLikYxRAF8fXWfPx7F+hzNqQIc1Q=; b=DSCXWB+AHA/qxkFdz+RJ727Tm0CjZr Ohr0F9aawutuKi2u3zfBKvY90p9ocmbKe6VuvXynLB7WgNj33gPPY1xHdLtNCEPA AfJBtoHdO8eq2bmfzEJqWdm70ZezgNgJNYwIwqDOfVnA14BcHcrjN6fsFX5Bcu5X n6UBDcph2sSN+r+2yQpjJfC2Q3o4w/4LMHn1IG75yUwFYoDyKWSvOGtgaDCbcWil Fb8m7QyprplJXhzjUJCS6NcJ6KIzy7VP0BPfeRltpEpPNAnSkv21GZaS8QrcMsop OWm6C5588EbBDQQKPsCX1JpylDIW5XqCvmt0BC0q4bBPLCa7O5TXQdig== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :resent-date:resent-from:resent-message-id:resent-to:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; bh=GLYTDl3AlhEBhiAdLikYxRAF8fXWfPx7F+hzNqQIc1Q=; b=aDQFdijm lpKlC799r4o4eziC/41UxdMxPNyVXSU8TPADq0Gdrs6SvI/RkhGgrEHdt83sNdNI VL0VwcsTw7Xs2RKiBFVdaf4lgGDzEvEdUGA07dkB186SJiimoSqdROS9J7g8C8PH WLxXIoSbSlMXmUmB51CDx4gPnaHnB6BrLx6PfTppuv1esML9dpbjPTVbep645UGC hCd2CJJ4G8TW+qMmnNqp8zKqDW0sdSOeQtnKyeLTXXPag7raX2eOGvMD0D3HbW5q j8VfKs/Cp6gSW7hdTDwmsLu1iEtXkMXMoAnBuiXpyLklw3bGzu2VfM1zWR7ffHh8 vifRo3Rnyeyu3A== X-ME-Sender: X-ME-Proxy: Original-Received: from Swift (freund-druck.geistwis.uni-wuppertal.de [132.195.204.212]) by mail.messagingengine.com (Postfix) with ESMTPA id 90A49102A0 for ; Wed, 24 Oct 2018 05:05:45 -0400 (EDT) Resent-From: Joost Kremers Resent-Date: Wed, 24 Oct 2018 11:05:43 +0200 Resent-Message-ID: <20181024090543.GB13100@Swift> Resent-To: emacs-devel@gnu.org Content-Disposition: inline In-Reply-To: X-Editor: Emacs of course! X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 66.111.4.27 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 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.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:230619 Archived-At: On Wed, Oct 24, 2018 at 12:51:35AM -0400, Richard Stallman 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. ]]] > > > In what sense is the above cl-case more clear than the pcase equivalent? > > I'm not saying the pcase version is better in those cases, but I think > > the respective advantages and disadvantages pretty much balance out. > > I also wonder. Is it simply that people find pcase unfamiliar? Well, I can't speak for others, but personally, though I find pattern matching as a concept straightforward and intuitive, pcase syntax seems unnecessarily complex and unintuitive. For example, John Wiegley's tutorial on pcase at has the following example: ``` (pcase value (`(,_ 1 2) (message "Matched a list of anything followed by (1 2)"))) ``` It is not clear to me why I couldn't simply write: ``` (pcase value ((_ 1 2) (message "Matched a list of anything followed by (1 2)"))) ``` I *can* understand the need to write: ``` (pcase value (`(1 2 ,foo 3) (message "Matched 1, 2, something now bound to foo, and 3"))) ``` Instead of: ``` (pcase value ((1 2 foo 3) (message "Matched 1, 2, something now bound to foo, and 3"))) ``` This is obviously done in order to be able to match against the symbol `foo' while at the same time be able to match anything and bind it to the symbol `foo'. And even though this syntax with backquote and comma looks familiar to anyone who's ever written a macro, their meaning is subtly different from their meaning in macros. In pcase, «,foo» does *not* mean «evaluate `foo'», it means something like «use `foo' as a variable». So, while I understand the reasoning, it still makes me wonder why I can't write something like this: ``` (pcase value ((1 2 % 3) (message "Matched 1, 2, something now bound to %, and 3"))) ``` That is, use a special symbol (I borrowed % from Clojure's anonymous functions) to indicate that I want to match against any value and at the same time bind that value. Obviously, the following: ``` (pcase value ((1 2 % %) (message "Matched 1, 2, something now bound to %, and that same something again"))) ``` would then match lists of the form (1 2 3 3), not (1 2 3 4). If you need to bind multiple values, I could imagine using something like: ``` (pcase value ((1 2 %1 %2) (message "Matched 1, 2, something now bound to %1, and something (else) bound to %2"))) ``` Also, the use of `pred' and `guard' seem unnecessary. Instead of: ``` (pcase value (`(1 2 ,(or 3 4) ,(and (pred stringp) (pred (string> "aaa")) (pred (lambda (x) (> (length x) 10))))) (message "Matched 1, 2, 3 or 4, and a long string " "that is lexically greater than 'aaa'"))) ``` why not write: ``` (pcase value ((1 2 (or 3 4) (and (stringp %) (string> "aaa" %) (> (length %) 10))) (message "Matched 1, 2, 3 or 4, and a long string " "that is lexically greater than 'aaa'"))) ``` Similarly, the example: ``` (pcase value (`(1 2 ,(and foo (guard (and (not (numberp foo)) (/= foo 10)))) _) (message "Matched 1, 2, anything, and then anything again, " "but only if the first anything wasn't the number 10")))) ``` uses `(and foo (guard ...))' to bind a value to `foo' and apply a predicate to it. That's a coding pattern that you need to be familiar with in order to understand what it does. (John explains it in his tutorial, but if I had met this in the wild, I'd probably be puzzled by it at first). The % syntax would seem to make this simpler as well: ``` (pcase value ((1 2 (and (not (numberp %)) (/= % 10)) _) (message "Matched 1, 2, anything, and then anything again, " "but only if the first anything wasn't the number 10")))) ``` This example also shows that `and' has a meaning in pcase that is subtly different from its usual meaning in Lisp: `and' in a pcase 'UPattern' (as the manual calls it) is not a logical `and' in the sense that it tests its arguments for truthiness. Rather, it means «both arguments of `and' must apply to the value at this position *regardless of truthiness*». (The `and' inside the guard does have the usual meaning, of course.) Mind you, I'm not arguing that pcase should be changed or replaced with something that has this more intuitive (to me, anyway) syntax. I'm just trying to explain why I personally find pcase difficult to wrap my head around, and why I think this difficulty has to do with its syntax, which is different in subtle ways, to such an extent that you can't, as an Elisp programmer tackling pcase for the first time, just build on what you already know. You need to actually bend your mind to incorporate the new stuff. Moreover, at first sight, there doesn't seem to be much of an advantage to this syntax, since an alternative syntax that doesn't have the same disadvantage seems feasible. I say "seems", because it's entirely possible that this particular syntax has capabilities that wouldn't be possible with a simpler syntax. But for a pcase newbie, that's not immediately obvious. The only reason that I can think of why the %-syntax or something similar isn't used is that it's dangerous in an environment that doesn't have lexical scope... Just my two cents, of course. -- Joost Kremers Life has its moments