From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Mark Oteiza Newsgroups: gmane.emacs.bugs Subject: bug#28254: 26.0.50; SRFI-2 and-let* Date: Sat, 2 Sep 2017 09:36:04 -0400 Message-ID: <20170902133604.GA27251@holos.localdomain> References: <87a82kdb4e.fsf@holos> <87inh36sap.fsf@users.sourceforge.net> <20170902021043.GA7509@holos.localdomain> <878thx7qcc.fsf@users.sourceforge.net> <20170902041424.GA21189@holos.localdomain> <87tw0lzn7w.fsf@drachen> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed X-Trace: blaine.gmane.org 1504359449 3721 195.159.176.226 (2 Sep 2017 13:37:29 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sat, 2 Sep 2017 13:37:29 +0000 (UTC) User-Agent: Mutt/1.8.3 (2017-05-23) Cc: 28254@debbugs.gnu.org, npostavs@users.sourceforge.net To: Michael Heerdegen Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Sep 02 15:37:14 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1do8bq-0000Ay-4J for geb-bug-gnu-emacs@m.gmane.org; Sat, 02 Sep 2017 15:37:14 +0200 Original-Received: from localhost ([::1]:48817 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1do8bx-0007oo-A1 for geb-bug-gnu-emacs@m.gmane.org; Sat, 02 Sep 2017 09:37:21 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:40481) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1do8bn-0007o8-NQ for bug-gnu-emacs@gnu.org; Sat, 02 Sep 2017 09:37:16 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1do8be-00051R-DI for bug-gnu-emacs@gnu.org; Sat, 02 Sep 2017 09:37:11 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:33217) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1do8be-00050g-7A for bug-gnu-emacs@gnu.org; Sat, 02 Sep 2017 09:37:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1do8bd-0006oK-Pk for bug-gnu-emacs@gnu.org; Sat, 02 Sep 2017 09:37:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Mark Oteiza Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 02 Sep 2017 13:37:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 28254 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 28254-submit@debbugs.gnu.org id=B28254.150435937526123 (code B ref 28254); Sat, 02 Sep 2017 13:37:01 +0000 Original-Received: (at 28254) by debbugs.gnu.org; 2 Sep 2017 13:36:15 +0000 Original-Received: from localhost ([127.0.0.1]:41896 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1do8at-0006nH-5x for submit@debbugs.gnu.org; Sat, 02 Sep 2017 09:36:15 -0400 Original-Received: from mail-qk0-f171.google.com ([209.85.220.171]:38043) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1do8aq-0006n1-S4 for 28254@debbugs.gnu.org; Sat, 02 Sep 2017 09:36:13 -0400 Original-Received: by mail-qk0-f171.google.com with SMTP id n64so5402702qki.5 for <28254@debbugs.gnu.org>; Sat, 02 Sep 2017 06:36:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=udel-edu.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=3ws9QuIKSEyAKMd2N9+SHIS43VrI71OTIVnSGo3XjJY=; b=EwbHSdb5BHP+IY3ewsQo/JkZ/MiFbzHv6aVWNuCyCYuVtLOrSvXmhmb55u0LtPPsUb zfog10c8JWfYVywsusa1F08VVGYMmdNBtPdW6dh8RA4l+RZ+TggzRTRna3d/ZOarahxu etHLGNQaxzkv5njT06sHNsl2MdEcIuZnWWglDdUKJ1mBJd7vdDU9M05KKlBT8mxh8KBo VWBi3XJCkTU8j/bZJB/sEiJRCqg6/l/pSDTojLlW0ntL+WpUyfRfetPzsD8xUQo/m4Ag Go8y+mySw+BHGmwTgmda0HQ/O82edES2Gbss6orkjrBPss0WUepNYxmRkydFLjoZC/56 Qntg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=3ws9QuIKSEyAKMd2N9+SHIS43VrI71OTIVnSGo3XjJY=; b=Ertm072/8FOtdBq4wtbEX0tSjTO6ECck34wJrvQK9y0jWzl+svUn8WTFn0pvUOLK5O e28kqyy0mmtqVHjOxmS08rfwDsDURiv/pAsQ4fVdlshxylRHd15UOPeipTDCcTN7Piih Mn3Bg4x5x2wgDqlUNxRs3rygaj329Kswot8jntvuFkowxCGnGOaiHzr0sVmoBisi9z8V oMbJeNfb4gbpokqQkNWCTOiIxqw8zNkqMBPEfOVSyf6YE50wxjx34G+lioN4eazE1F5u ar0Na9jQDF8c5+s7ywfl0HkjpYdN+OHm2ATj+gBft2+CYD2svKesUEIIYHTkZptNbJFB s+QQ== X-Gm-Message-State: AHPjjUj3u1AEE5VzkwjQbCqx6IzqPMpfVcraJ4TnqcvsmK17wXZG30xp fptPM/9eZod3vh5pIJUrLw== X-Google-Smtp-Source: ADKCNb7N+ubcwBxV8rg+vs+zvof7HTnD3UUA7S1k+G+0pzh4sBi9QDzO3q4TRBdfJGQjfwDJHgImvA== X-Received: by 10.55.212.90 with SMTP id l87mr6545470qki.218.1504359366878; Sat, 02 Sep 2017 06:36:06 -0700 (PDT) Original-Received: from holos.localdomain (pool-173-64-88-95.bltmmd.fios.verizon.net. [173.64.88.95]) by smtp.gmail.com with ESMTPSA id f6sm1845369qtb.68.2017.09.02.06.36.05 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 02 Sep 2017 06:36:05 -0700 (PDT) Original-Received: by holos.localdomain (Postfix, from userid 1000) id 0BDBB69C52; Sat, 2 Sep 2017 09:36:05 -0400 (EDT) Content-Disposition: inline In-Reply-To: <87tw0lzn7w.fsf@drachen> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 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.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:136485 Archived-At: On 02/09/17 at 07:25am, Michael Heerdegen wrote: >Mark Oteiza writes: > >> >> I didn't try writing it in the style of if-let*--perhaps if-let* could >> >> be extended and all three macros would learn (EXPR). >> > >> >Yes, I think it's best if all foo-let* macros interpret the varlist in >> >the same way. >> >> Alright, I'll look at it. > >Isn't there a problem with EXPR being a symbol S, which already has a >different meaning (bind S to nil)? Though, this seems barely useful to >me. Anyway, introducing (EXPR) would thus be backward incompatible. Yeah, that is true. The following patch implements most of the previous, except it doesn't specially handle EXPR being just a symbol. All the incumbent subr-x-tests pass. This single tuple special case is troublesome IMO: (if-let* (x) "dogs" "cats") => "cats" (if-let* (x (y 2)) "dogs" "cats") => (void-function y) (if-let* (x (y 1) (z 2)) "dogs" "cats") => "cats" I'm curious if this was brought up in the old discussion when this was implemented. diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 849ac19d6a..eeacdbcfcd 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -83,10 +83,16 @@ thread-last `(internal--thread-argument nil ,@forms)) (defsubst internal--listify (elt) - "Wrap ELT in a list if it is not one." - (if (not (listp elt)) - (list elt) - elt)) + "Wrap ELT in a list if it is not one. +If ELT is of the form ((EXPR)), listify (EXPR) with a dummy symbol." + (cond + ((nlistp elt) (list elt)) + ((atom (car elt)) elt) + ((and (null (cdr elt)) + (let ((form (car elt))) + (or (listp form) (atom form)))) + (list (cl-gensym) (car elt))) + (t elt))) (defsubst internal--check-binding (binding) "Check BINDING is properly formed." @@ -122,8 +128,11 @@ if-let* Each binding is evaluated in turn with `let*', and evaluation stops if a binding value is nil. If all are non-nil, the value of THEN is returned, or the last form in ELSE is returned. + Each element of VARLIST is a symbol (which is bound to nil) or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM). +An element can additionally be of the form (EXPR), which is +evaluated and checked for nil. In the special case you only want to bind a single value, VARLIST can just be a plain tuple. \n(fn VARLIST THEN ELSE...)" @@ -134,18 +143,23 @@ if-let* (not (listp (car bindings)))) ;; Adjust the single binding case (setq bindings (list bindings))) - `(let* ,(internal--build-bindings bindings) - (if ,(car (internal--listify (car (last bindings)))) - ,then - ,@else))) + (if bindings + `(let* ,(setq bindings (internal--build-bindings bindings)) + (if ,(caar (last bindings)) + ,then + ,@else)) + `(let* () ,then))) (defmacro when-let* (bindings &rest body) "Bind variables according to VARLIST and conditionally eval BODY. Each binding is evaluated in turn with `let*', and evaluation stops if a binding value is nil. If all are non-nil, the value of the last form in BODY is returned. + Each element of VARLIST is a symbol (which is bound to nil) or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM). +An element can additionally be of the form (EXPR), which is +evaluated and checked for nil. In the special case you only want to bind a single value, VARLIST can just be a plain tuple. \n(fn VARLIST BODY...)" @@ -154,7 +168,12 @@ when-let* (defalias 'if-let 'if-let*) (defalias 'when-let 'when-let*) -(defalias 'and-let* 'when-let*) + +(defmacro and-let* (varlist &rest body) + "Bind variables according to VARLIST and conditionally eval BODY. +Like `when-let*', except if BODY is empty and all the bindings +are non-nil, then the result is t." + `(when-let* ,varlist ,@(or body '(t)))) (defsubst hash-table-empty-p (hash-table) "Check whether HASH-TABLE is empty (has 0 elements)."