3 ms·
OK, 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,
by AceJohnny2 10y ago
OK, 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.
- zeveb 10y agoYup. And the reason not to default to a list of then-forms and a list of else-forms is partly æsthetic, but partly dealing with the common case, because: (if (eq foo bar) (baz)) looks like a function call, not returning the value of baz (using your syntax). And of course Lisp is often written in a semi-functional way, so PROGN is, while not rare or really even avoided, not the usual way of doing things, usually.
- kazinator 10y agoThere cannot be an implicit progn for both! Because we don't know where one ends and the other begins. That is, unless we introduce a signal, like an else keyword/label which separates them, like this: (if cond form form form else form form form) Such macros have existed. A certain John Foderaro of Franz, Inc. was (is?) known for favoring and promoting his if{star} macro. (Of course I mean asterisk by {star} which HN won't let me type). Info here: http://franz.com/~jkf/coding_standards.html http://franz.com/~jkf/coding_standards.html http://franz.com/support/documentation/6.0/doc/operators/excl/if_s.htm http://franz.com/support/documentation/6.0/doc/operators/exc... Your idea is certainly doable: (my-if cond (then-form then-form ...) (else-form else-form ...)) The macro is trivial: (defmacro my-if (cond then-forms &optional else-forms) `(if ,cond (progn ,@then-forms) (progn ,@else-forms))) I've always resisted writing this macro because I felt it has a slight readability issue: (my-if (some condition) ((consequent) (consequent2) (consequent3)) ((alternative) ;; relatively quiet signal here (alternative))) Maybe it's not that bad, after all. Still, it's just saving a few keystrokes to insert progn and doesn't buy much over cond, which is more general, allowing multiple conditions: (cond ((some condition) (consequent) (consequent2) (consequent3)) ((other condition) (other) (other2)) (t (alternative) (alternative))) NOTE: cond existed in Lisp first, as a special form. The if macro came later as a syntactic sugar for simple situations involving just one condition! The thing is that if you keep most of your code functional, a lot of this is moot. We need multiple statements when we are doing something imperative. There is never any reason to have (progn S1 S2) unless S1 has a side effect. If S1 has no side effect, then this is equivalent to (progn S2), which is just S2. If you avoid side effects, the you don't need any progn most of the time (implicit or not). This is why progn is called what it is; it's Lisp's feature for writing a "program" (in the sense of an imperative list of things to do). Well, "prog" is that feature; and "progn" is the variant which returns the value of the n-th form. Another mitigation is that lot of the time code binds variables anyway with a let: (if condition (let (... vars ...) this that) (let (.... other vars ...) other))