6 ms·
That's common in Lisps. Just use cond and when if it bothers you.
by qwertyuiop924 10y ago
That'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.