emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Sweeter Emacs Lisp


From: Drew Adams
Subject: RE: Sweeter Emacs Lisp
Date: Sat, 10 Aug 2013 09:27:14 -0700 (PDT)

> >    > 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
> >        (<test1> <body1>)
> >        (let x <foo>)
> >        (<test2> <body2>))
> >
> >    which would be used in cases where we currently use
> >       (let (x)
> >         (cond
> >          (<test1> <body1>)
> >          ((progn (setq x <foo>) <test2>) <body2>))
> 
> 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.

+1

> In this aspect, RMS' suggestion is better.

It's better, but it too is not a great idea, IMO.  Clearest of
all is what y'all *started* with - plain ol' lisp:

(let (x)
  (cond ((...x...)
         ...)
        ((progn (setq x ...) ...) 
         ...)))

or more likely:

(cond ((let ((x ...))...)
       ...)
      ((let ((x ...))...)
       ...))

or typically clearer, when possible (e.g., subforms refer to the
variable explicitly or do not evaluate code that refers to it):

(cond ((let ((x1 ...))...)
       ...)
      ((let ((x2 ...))...)
       ...)

depending on the need/context.

> 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))
>
> --> (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))

Quelle horreur ! The second (the macroexpansion of the first) is
more readable than the first.

And the second is but a mechanical expansion.  A human would write
something simpler, e.g. (and (< x z) 4) instead of (cond ((< x z) 4)).

And with average-length function and variable names the second form
is not much more verbose than the first.  Saving a few parens and
explicit conditionals at the expense of clarity wrt scope etc. is
usually an unwise trade-off.

YAGNI.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]