From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: "Garreau\, Alexandre" Newsgroups: gmane.emacs.devel Subject: Re: Why is there no `until' in elisp? Date: Wed, 17 Oct 2018 02:12:13 +0200 Message-ID: <87y3axjusi.fsf@portable.galex-713.eu> References: <87murdu6to.fsf@portable.galex-713.eu> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Trace: blaine.gmane.org 1539735081 1798 195.159.176.226 (17 Oct 2018 00:11:21 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 17 Oct 2018 00:11:21 +0000 (UTC) User-Agent: Gnus (5.13), GNU Emacs 25.1.1 (i686-pc-linux-gnu) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Oct 17 02:11:16 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 1gCZQi-0000P2-AV for ged-emacs-devel@m.gmane.org; Wed, 17 Oct 2018 02:11:16 +0200 Original-Received: from localhost ([::1]:60665 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gCZSo-0003ag-Ip for ged-emacs-devel@m.gmane.org; Tue, 16 Oct 2018 20:13:26 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:46703) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gCZRx-0003Ty-10 for emacs-devel@gnu.org; Tue, 16 Oct 2018 20:12:33 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gCZRu-0000WY-L0 for emacs-devel@gnu.org; Tue, 16 Oct 2018 20:12:32 -0400 Original-Received: from portable.galex-713.eu ([2a00:5884:8305::1]:41456) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gCZRn-0000Gg-Ne for emacs-devel@gnu.org; Tue, 16 Oct 2018 20:12:26 -0400 Original-Received: from localhost ([::1] helo=portable.galex-713.eu) by portable.galex-713.eu with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1gCZRe-0001wv-0n; Wed, 17 Oct 2018 02:12:14 +0200 X-GPG-FINGERPRINT: E109 9988 4197 D7CB B0BC 5C23 8DEB 24BA 867D 3F7F X-Accept-Language: fr, en, it, eo In-Reply-To: (Stefan Monnier's message of "Tue, 16 Oct 2018 17:28:28 -0400") X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:5884:8305::1 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:230430 Archived-At: I do also believe `until' is actually more important than `while', first of all, as I said, we can see that because it is more used in human language, this is also the case because `while', in its condition, refers to a both initial and transient state, while `until' refers to its final state, which is what should interest us the most (especially in functional programming that should be more interested at the result than the source). However I believe in minimalism, and I=E2=80=99m surprised you found someth= ing different and incompatible, but still, I find, very very interesting: I think `until' should refer to the version I gave because this is probably the one which is going to be implemented naively by most people, also it can be useful to try to retrieve the last body return value, just as it is with `while': it is usually something you computed, not some potential binary boolean that you might have known since the beginning. And then, of course, this introduce useless discrepancy toward symmetry within respect `while'. So your version should have a different (maybe longer? I hope the least) name. A trivial symetric `while' to yours is one that keeps the last true value: `(let (res) (while (and! res ,test) ,@body) res) (while introducing the notation fun![0]). It may sound artificial but it is not, look thereafter. I recently felt a big need of a form acting both as a `when' and a `prog1' (a `when' that returns its condition / first argument), and symetricaly for `unless' (in the end I used a (when-let ((var val)) (prog1 var . body)), but I=E2=80=99m pretty unsatisfied, like always when i= t=E2=80=99s about finding an optimum in extreme factorization, maybe sometimes it=E2=80= =99s not possible). This is no different. This also recalled me that, but this might be a separate discussion, a long time ago, when discovering cyclic lists through experimentation, I thought that `while' could be implemented this way: `(and (prog1 . body) . #1), and for until: `(or (prog1 . body) . #1). And your until is precisely that. Now you also got your interesting counterpart for `until'. While my minimal `until' is to yours what `progn' is to `prog1'. Let=E2=80= =99s call yours `until1', then `until' is (let (res) (until1 test (setq res (progn . body)))) (I still fill like a relation between both might be better and more elegantly expressed=E2=80=A6 though the same stands for when-prog1). Another interesting version I dreamt of is the one that returns a list of the return value of each iteration (in may be useful in both mine and yours version): (lazy-map (lambda (var) . body) '(cons test (or test #0))) (or any way of stopping to map/concat when it is returning nil). [0] so that, for any `fun' where `fun!' (an imperative, side-effects targeted, version of fun) is undefined: (fun! var . args) stands for (setq var (fun! var . args)), such as (+! var 1 2) is (setq var (+ var 1 2)), (not! var) is (setq var (not var)) and (and! var bool1 bool2) is (setq var (and var bool1 bool2) (this is all equivalent to C =E2=80=9C+=3D= =E2=80=9D, =E2=80=9C!=3D=E2=80=9D and =E2=80=9C&=3D=E2=80=9D (or better: C++ =E2=80=9C&&=3D=E2=80=9D)).