5 ms·
I've been using Emacs for over a decade now. Every now and then (say, once a week), I feel the need to fiddle with some ELisp code. I read Stevey's Emergency E
by AceJohnny2 10y ago
I've been using Emacs for over a decade now. Every now and then (say, once a week), I feel the need to fiddle with some ELisp code.
I read Stevey's Emergency Elisp guide:
http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html
I reached the part about the then clause of if/then/else needing a (progn ...) if it was to be a multi-statement clause, but the else clause doesn't. But you can avoid the progn if you don't have an else clause by using when instead of if!
I facepalmed so hard I needed reconstructive surgery. I haven't fully recovered from that. (in reality it's because, though ELisp itself is bad enough, Emacs' API is daunting)
- qwertyuiop924 10y agoThat's common in Lisps. Just use cond and when if it bothers you.
- AceJohnny2 10y agoWhy do Lisps separate these related semantics? Are there implementation reasons, or is it mostly "the way it's always been"? Edit: thanks folks! You've helped me get over the facepalm from years ago :)
- foldr 10y agoI'm confused by this question. What would the alternative be?
- AceJohnny2 10y agoJust if (or cond), no alternative-form when or cond (resp. if)
- hibbelig 10y agoThe alternative forms are just syntactic sugar. Don't you like sugar? (But the basic form is "cond".) (In C, you can say "x = x + 1" or "x += 1" or "x++", where the first one is enough. Still I like having the other two.)
- qwertyuiop924 10y agoFirstly, because the way Lisp is structured makes it impractical to have implicit progn (or implicit begin in the schemes) in if. Secondly, because lisp, while not a functional language, has functional leanings: you would be surprised how often it is that one form is all you need.
- lispm 10y agoWell, Common Lisp has such a construct built in: CL-USER 48 > (LOOP REPEAT 2 FOR number = (READ) IF (> number 0) DO (princ '(the number is larger than 0)) (print 'true) (terpri) ELSE DO (princ '(the number is not larger than 0)) (print 'false) (terpri)) 2 (THE NUMBER IS LARGER THAN 0) TRUE -2 (THE NUMBER IS NOT LARGER THAN 0) FALSE NIL It is also not that difficult to write a multi-expression IF. Here is a sketch: (defmacro if* (cond &rest conseq) (let ((p cond) (thenpos (position 'then conseq)) (elsepos (position 'else conseq))) (cond ((and thenpos elsepos) `(if ,p (progn ,@(subseq conseq (1+ thenpos) elsepos)) (progn ,@(subseq conseq (1+ elsepos))))) (thenpos `(when ,p ,@(subseq conseq (1+ thenpos)))) (elsepos `(unless ,p ,@(subseq conseq (1+ elsepos))))))) Then we can write: (if* (> pi 0) then (print 'a) (print 'b) else (print 'c) (print 'd)) and (if* (> pi 0) then (print 'a) (print 'b)) and (if* (> pi 0) else (print 'a) (print 'b))
- qwertyuiop924 10y agoIf it's part of LOOP, than it's not part of the language, now is it? Well, it is, but you can't do it in the general case. You can define a macro for it, though.
- TeMPOraL 10y agocond actually is a predecessor of if/else you know from other languages. Yes, it was first. As for progn, it's pretty much the equivalent of curly braces from C-like languages (or of the comma operator, if you care about its value). Why if seems to be commonly defined as (condition then-clause &rest else-clauses) instead of (condition then-clause else-clause), I don't know. History/common use patterns, probably?
- yarrel 10y agoIt's very tempting to write: (if a (something because of a) (something more because of a)) Requiring a progn for the else clause means that the above is caught by the compiler.
- swhipple 10y agoThat is true, but somewhat alleviated by Emacs' choice to indent the THEN form at a different level than [ELSE]*. A novice would notice that the code looks incorrect as they were typing it.
- zeveb 10y ago> Why do Lisps separate these related semantics? It's not really separating related semantics; it's that an if-then-else option has to have both a then clause and and else clause. (IF then else) is a natural way to express that, but it does mean that if you want to do more than one thing in the then clause then you'll need to have a PROGN. You could have multiple statements in the else clause (which is what emacs does). In Common Lisp, the syntax is: if test-form then-form [else-form] => result* In emacs, it's: if test-form then-form [else-form]* => result* I think that the emacs form is weird and annoying, but might make certain forms of code easier (e.g. check for something and short-circuit, else calculate something more deeply). COND is a different beast entirely. Note that WHEN & UNLESS both have an implicit PROGN.
- AceJohnny2 10y agoOK, so the weirdness is really that Emacs' else-form accepts multiple statements, and/or that there is no implicit progn for both then-form and else-form. I.e, I would've expected something like this: (if (condition) ( (then do something) (and more things) ) ( (else do something else) (and more other things) ) ) (and yeah, I'm definitely showing my C-semantic preferences here aren't I?)
- qwertyuiop924 10y agoThat's closer to cond: (cond (<condition1> <body>*) (<condition2> <body>*) (else <body>))
- kazinator 10y agoNot in Common Lisp, that: else is just a variable reference here. Unbound, if you're lucky; bound to a true value if you're somewhat less lucky, and bound to nil if you're haplessly unfortunate. :)
- qwertyuiop924 10y agoAh. I forgot about that. See, this is what happens when you know Scheme better than CL.
- hibbelig 10y agoIt's just a consequence of the Lisp syntax: (if COND THEN ELSE), so this list has four elements, and the second is the condition, the third is one leg, and the last is the other leg. How would you make the "THEN" part longer, except by wrapping parens around it? To use a metaphor: In typical infix languages, I can only add two numbers, not three. Why do I need to do strange things like using two plus signs as in "3 + 4 + 5" to add three numbers? Lisp can do it with one: (+ 3 4 5) The answer to this metaphor is that the very idea of infix results in this limit. In the same way, the very idea of expressing everything as s-expressions results in that limitation.
- akkartik 10y agoYou might be interested in this ancient discussion on the Arc Forum about the benefits and drawbacks of Lisp conditionals: http://arclanguage.org/item?id=18218 http://arclanguage.org/item?id=18218