From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Pascal J. Bourguignon" Newsgroups: gmane.emacs.devel Subject: Re: Sweeter Emacs Lisp Date: Sat, 10 Aug 2013 12:08:05 +0200 Organization: Informatimago Message-ID: <8761vdoo3e.fsf@informatimago.com> References: <8738rh6ftk.fsf@gnu.org> <87a9lezh9w.fsf@zigzag.favinet> <8738r5zyap.fsf@zigzag.favinet> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1376129992 9940 80.91.229.3 (10 Aug 2013 10:19:52 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 10 Aug 2013 10:19:52 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Aug 10 12:19:55 2013 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1V86H3-0005ab-Fe for ged-emacs-devel@m.gmane.org; Sat, 10 Aug 2013 12:19:53 +0200 Original-Received: from localhost ([::1]:41176 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V86H3-0004ga-0F for ged-emacs-devel@m.gmane.org; Sat, 10 Aug 2013 06:19:53 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:56722) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V866E-0003AJ-QI for emacs-devel@gnu.org; Sat, 10 Aug 2013 06:08:47 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V866A-0005w0-2x for emacs-devel@gnu.org; Sat, 10 Aug 2013 06:08:42 -0400 Original-Received: from plane.gmane.org ([80.91.229.3]:42047) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V8669-0005ve-PJ for emacs-devel@gnu.org; Sat, 10 Aug 2013 06:08:38 -0400 Original-Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1V8667-0006OF-Jf for emacs-devel@gnu.org; Sat, 10 Aug 2013 12:08:35 +0200 Original-Received: from amontsouris-651-1-13-20.w90-46.abo.wanadoo.fr ([90.46.104.20]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 10 Aug 2013 12:08:35 +0200 Original-Received: from pjb by amontsouris-651-1-13-20.w90-46.abo.wanadoo.fr with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 10 Aug 2013 12:08:35 +0200 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 130 Original-X-Complaints-To: usenet@ger.gmane.org X-Gmane-NNTP-Posting-Host: amontsouris-651-1-13-20.w90-46.abo.wanadoo.fr Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9 033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR mV+hO/VvFAAAAABJRU5ErkJggg== X-Accept-Language: fr, es, en User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux) Cancel-Lock: sha1:ODQyYWRhNTI5ODc0MzA0NTRkYjlhNDk5YTVkMmQyNDgzNzI0YTExYg== X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 80.91.229.3 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 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-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:162547 Archived-At: Thien-Thi Nguyen writes: > () Stefan Monnier > () Mon, 22 Jul 2013 17:04:04 -0400 > > > RMS suggested instead: > > (cond VAR (CONDITION [BODY...]) > > ...) > > As I pointed out back then, a more general solution is a way to > let-bind new variables in between cond clauses, as in > > (cond > ( ) > (let x ) > ( )) > > which would be used in cases where we currently use > > (let (x) > (cond > ( ) > ((progn (setq x ) ) )) I don't like it. The general idiom in lisp, and including in emacs lisp, is to have a close correspondance between parentheses and lexical scope. Whether x is in the englobing scope, or in a scope covering only the remaining clauses, in both cases it's bad because it's not reflected by the sexp structure of the form. In this aspect, RMS' suggestion is better. I would advise a form rather like: (letcond ((f) 1) (let* ((x (g)) (y (h x))) ((= x y) 2) ((< x y) 3) (let ((z (p))) ((< x z) 4)) (t 5)) ((q) 6) (t 0)) (defun letcond-generate-let-clause (let-clause) (destructuring-bind (let bindings &body body) let-clause `((,let ,bindings (cond ,@(letcond-generate-cond-clauses body)))))) (defun letcond-generate-cond-clauses (clauses) (mapcar (lambda (clause) (if (member (first clause) '(let let*)) (letcond-generate-let-clause clause) clause)) clauses)) (defmacro letcond (&rest clauses) `(cond ,@(letcond-generate-cond-clauses clauses))) (pprint (macroexpand-1 '(letcond ((f) 1) (let* ((x (g)) (y (h x))) ((= x y) 2) ((< x y) 3) (let ((z (p))) ((< x z) 4)) (t 5)) ((q) 6) (t 0)))) --> (cond ((f) 1) ((let* ((x (g)) (y (h x))) (cond ((= x y) 2) ((< x y) 3) ((let ((z (p))) (cond ((< x z) 4)))) (t 5)))) ((q) 6) (t 0)) Notice how emacs already knows how to indent it to show the correct scopes! Yes, within a letcond, let and let* take another meaning (they are interpreted specially by the letcond macro) when in the place of a clause condition. In general I dislike those overloading, but I think in this case it may be acceptable and the best solution, even if it prevents you to use a variable named let or let*; you can always use cond to test such a variable, or use (identity let): (letcond (let ((let 'let)) ((identity let) let) (t nil))) --> let vs. the surprizing: (letcond (let ((let 'let)) (let nil) (t let))) --> let (letcond (let ((let 'let)) (let let) (t nil))) Debugger entered--Lisp error: (wrong-type-argument sequencep let) -- __Pascal Bourguignon__ http://www.informatimago.com/ A bad day in () is better than a good day in {}. You know you've been lisping too long when you see a recent picture of George Lucas and think "Wait, I thought John McCarthy was dead!" -- Dalek_Baldwin