[Top][All Lists]

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

RE: if vs. when vs. and: style question

From: Drew Adams
Subject: RE: if vs. when vs. and: style question
Date: Mon, 23 Mar 2015 17:22:59 -0700 (PDT)

> assuming (e1) and (e2) are some expressions, all three forms:
> (if (e1) (e2))
> (when (e1) (e2))
> (and (e1) (e2))

Plus `cond', `unless', `or', and `not'.

> are semantically equivalent.  Which one is better style (and when)?
> I would guess that =when= is better iff (e2) is a =progn= (since we can
> drop the =progn= altogether, and this seems to be the point of =when=),
> and =and= might be considered better (well, maybe) by some people when
> both (e1) and (e2) are very short (though I personally would avoid that,
> since =if= seems easier for a human to understand at a first glance).
> Am I right?
> Notice: by “better” I mean “more idiomatic”, or “easier/faster to read
> for a human”, or “more likely to be used by an experienced Elisp
> hacker”, etc.


I use a convention that you will find mentioned in "Common Lisp
The Language" (1 & 2):

I use `if', `and', and `or' when the return value is significant
(i.e., it is used; it makes a difference to the behavior).

I use `when' and `unless' _only_ when the return value is not
significant (not used).  IOW, they signify side effects only, when
I read them (in code I wrote).


Beyond that -

I use `cond' in both contexts (whether or not the return value is used).

I use `if' _only_ for the if-then-else case (3 args, not 2).  For the
if-then case (only two args) I use `and' or `or' (if the return value
is significant) or `when' or `unless' (if the return value is not used).

For `(if test nil val)' I typically use `(and (not test) val)'.
But sometimes I use (if test nil other-val), if I really want to point
out the nil return possibility (esp. if I want to put a comment on
its line).

Similarly, for `(if test val nil)' I typically use `(and test val)'.

I typically use `(cond (test foo1 foo2...) (t bar1 bar2...))' instead
of `(if test (progn foo1 foo2...) bar1 bar2...)'.

I typically use `(if test val sexp1 sexp2...)' instead of
`(cond (test val) (t sexp1 sexp2...))'.  But sometimes I don't. ;-)

And yes, I typically use a single `setq' for sequential assignments.
And that means that I can use `(if test (setq...) val)' instead of
`(if test (progn (setq...) (setq...)...) val)'.

Because I use a single `setq' for multiple assignments, seeing two
`setq's "next to" each other makes clear that they are at different
levels; they are not siblings.  E.g.


In a `setq' with multiple assignments (and in a `let' with multiple
bindings) I typically align the values too, not just the variables:

(setq toto    kelp
      bar     rhinoceros
      whoops  nematode)


I also use `()' instead of nil when it represents the empty list.

And I use an explicit initialization to `nil' or `()' in a `let',
if it is a true initialization.  That is, I put a variable in a
`let' without any initial value _only_ if its initial value is
assigned in the `let' body, i.e., without making any use of its
implicit initial nil value.  

And I put any variables that have no initial binding at the end
of the list of bindings (not at the beginning, and not in between).

And yes, these conventions mean that I have to rewrite code from
one form to another as it evolves.  Not a big deal, to me.
Reading code is more important, to me.

I make no claims about others sharing such conventions.

reply via email to

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