From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Adam Porter Newsgroups: gmane.emacs.devel Subject: Re: Instead of pcase Date: Tue, 12 Dec 2023 19:32:09 -0600 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="7398"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mozilla Thunderbird Cc: emacs-devel@gnu.org To: rms@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed Dec 13 02:33:26 2023 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 1rDE7p-0001hA-Jp for ged-emacs-devel@m.gmane-mx.org; Wed, 13 Dec 2023 02:33:26 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rDE6o-0003Sx-8U; Tue, 12 Dec 2023 20:32:22 -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 1rDE6j-0003QY-QV for emacs-devel@gnu.org; Tue, 12 Dec 2023 20:32:18 -0500 Original-Received: from dragonfly.birch.relay.mailchannels.net ([23.83.209.51]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rDE6h-0006ru-Cb; Tue, 12 Dec 2023 20:32:17 -0500 X-Sender-Id: dreamhost|x-authsender|adam@alphapapa.net Original-Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 3F1E8761D9F; Wed, 13 Dec 2023 01:32:11 +0000 (UTC) Original-Received: from pdx1-sub0-mail-a212.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id DFEC3761EBB; Wed, 13 Dec 2023 01:32:10 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1702431130; a=rsa-sha256; cv=none; b=eW7om4UnCyDTwQhmNBxdeL35vXSQqmWTS74oF9S/iODKf3SINq0nonaQStMCqZ1gGLZvj/ jBXz2IrTl3ArE8F5QTYNyfbA6qWl9q2P3q9bEstukZCfuy+cLDpVA1dNHzV/OjNbX0FN6P OiYogZkTy6fv47OT+cAcU0vh7QmmElPytd+8FEaDfMbDGmW1qyyIo7dC60H5yJRk38ktEV jyno21lIhOjSm/Obz9gGlyQTC6V+7471vqWquJtIpuWEf/jCD8PetqW6D1qo3oaFeuGh+d XQR7LEe5ZWMgalf47fG9RCnSkJVx/NlE/2LieCQ8Ih/uAYDach9GTOxDlPVTog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1702431130; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=juAD3fjrDIVpA+vhkmRV65Z855+IM20eJLRcwHOhUR8=; b=Rc79HuXIpL9mM09J+CcPgiSfk3Cqn2tw+aZ41MTng/ztXpD3cbbTtbFTlZs8WcHCNHNW2f qqnHDFqacasD/Wl733zhDL9AI9zqxf3d8KwAsp11i6LzHjhK2tOcJVY0Pz8HJyoTsaaAh2 pD3HcnpJ2KQjH+4Lkeg02NlSAbziqMuyRqBZ8OnHCHl5AkSq0rEZTjMgJIFn9rGQ9e6aZD 4EWGQSji6km9TQbUdvW9LdricR02cu/kcc8IKPCkSoy5x5UJKa5rY4PjkkDAxVShr4vJJr yOr0vvI71U+jiFFHpZeHLwbJ6G9PNTpvYqEin5VwcdiwpkKZTGkzwGxpAS5aVg== ARC-Authentication-Results: i=1; rspamd-5749745b69-rx89d; auth=pass smtp.auth=dreamhost smtp.mailfrom=adam@alphapapa.net X-Sender-Id: dreamhost|x-authsender|adam@alphapapa.net X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|adam@alphapapa.net X-MailChannels-Auth-Id: dreamhost X-Callous-Cold: 6efaaaa13e9fecef_1702431131049_3656291168 X-MC-Loop-Signature: 1702431131049:713781761 X-MC-Ingress-Time: 1702431131049 Original-Received: from pdx1-sub0-mail-a212.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.124.185.79 (trex/6.9.2); Wed, 13 Dec 2023 01:32:11 +0000 Original-Received: from [10.45.3.58] (unknown [45.131.192.7]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: adam@alphapapa.net) by pdx1-sub0-mail-a212.dreamhost.com (Postfix) with ESMTPSA id 4SqdJB3QPLz3h; Tue, 12 Dec 2023 17:32:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alphapapa.net; s=dreamhost; t=1702431130; bh=juAD3fjrDIVpA+vhkmRV65Z855+IM20eJLRcwHOhUR8=; h=Date:To:Cc:Subject:From:Content-Type:Content-Transfer-Encoding; b=UjVgUd32gy9MWs2Hg1eFP2Vk09EXRjiItMIAKh+WKy0mC4YbXvb8ckBPtId/T4Do5 PtRuPADCt+8ei/rqa6Vf6A00RR0iCT7VP1DyAhOsF1omi8K7No88gitdTPhzrR8Y4n diobjoZfUohcKTvNGqkQHckGam6BoH5XfnjjVS4ypBy9cEzZkHASa7rEBcHgefDdfs VT0uvLSsB/+rQOBxaqP+AGn879/0siDhLKi+cqNB5vAfWgPhTZ5J6Ru9zywOWubk7z tt4Am/5y0OFV9xzYKdsndQSNiXJriMm/kV0Jke/eYG2+RpjEJFw+D7fFwS1FyHMwGT 16q/Cf9Z3ApOg== Content-Language: en-US In-Reply-To: Received-SPF: neutral client-ip=23.83.209.51; envelope-from=adam@alphapapa.net; helo=dragonfly.birch.relay.mailchannels.net X-Spam_score_int: -12 X-Spam_score: -1.3 X-Spam_bar: - X-Spam_report: (-1.3 / 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, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_NEUTRAL=0.779, 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:313736 Archived-At: Hi Richard, > I think whoever wrote that code in byte-optimize-letX was fascinated > by the challenge of writing as much as possible in pcase language > and minimizing use of Lisp. > > Here's my version, which I think is a lot clearer. > > It illustrates some of the flexibility of cond*: > * Use of ordinary Lisp fir conditions, > * Matching against different objects. > * Clauses that bind and then drop through. Respectfully, I disagree that this example is clearer than the original pcase form.[0] I'll explain why: > (defun byte-optimize-letX (form) > (cond* > ;; Bindings list is empty. > (:match (`(,_ () . ,body) form) > `(progn . ,body)) This is nearly identical to the equivalent pcase syntax, only adding `:match'. Since pcase's (and I suppose cond*'s) purpose is pattern matching, this seems redundant and unnecessarily verbose. > ;; Decompose the form > (:match (`(,head ,bindings . ,body) form)) I suppose it is largely a matter of taste, but I strongly dislike fall-through clauses. While it seems convenient here, as it allows the removal of either a redundancy (reiterating bindings in multiple clauses) or a level of nesting, its bindings are also implicit rather than explicit, as the scope of the binding form is not enclosed by visible boundaries (i.e. parens). One also wonders what it would look like if such a cond* form had multiple, overlapping fall-through bindings of the same variables--that would seem to be necessary in some cases, and would likely be confusing. Finally, forms which allow fall-through clauses are known to be more prone to human error than forms which don't allow them--and they don't seem syntactically "lispy." So I think this is more confusing than pcase, not less. > ;; Body is empty or just contains a constant. > (:match ((or `() `(,(macroexp-const-p const))) body) This seems even more confusing to me. The equivalent pcase form is: `(,head ,bindings . ,(or '() `(,(and const (pred macroexp-const-p))))) While the `and' keyword's being used to bind `const' may be surprising to those unfamiliar with pcase,[1] at least it explicitly binds the form to the variable before using it, and the scope of the binding is visible (being within that clause). In contrast, the cond* example appears to implicitly bind `const' by the symbol's being present in the predicate form as an argument. This seems much less clear to me. It also seems error-prone, as in a case where `const' were already bound. As well, what if the user needed to pass an already-bound argument in addition to the one being bound there? With pcase, the binding would be explicit, and the accompanying `guard' expression would have a clear place in lexical scope, so there would be no doubt about where the arguments were bound. With cond*, would the binding apply to the first argument symbol or a later one? If the goal is to avoid implicit rather than explicit behavior, that seems contrary to the goal. For these reasons, this seems more confusing to me than pcase, not less. Sincerely, Adam 0: https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/emacs-lisp/byte-opt.el?id=75fd7550ed6cede6c9e8224f1f2d62637c43fdd4#n1459 1: Perhaps we could recommend a minor change to pcase that might improve understanding: a `bind' keyword could be used to explicitly bind variables, rather than only having the implied binding from the `and' keyword (since `let' already has a different purpose in pcase). So the example from earlier could look like: `(,head ,bindings . ,(or '() `(,(and (bind const) (guard (macroexp-const-p const))))))