Cond and Let/Let*


1. cond

This is a shorthand for a nested if. The entire form consists of a set of clauses. Each clause consists of a condition and then any number of actions. The condition is evaluated, and if true (non-NIL), all the actions are evaluated, the value of the last one is returned, and the cond exits. Otherwise the process is repeated for the next clause. Since T is always non-NIL, it is often used as the condition for an "otherwise" clause.

Example:

(setq X 4)
(cond
  ((oddp X)  (+ X 3))
  ((evenp X) (+ X 2))
  ((< X 9)   999) )      ; This would be true, but is never reached
==> 6

(cond
  ((listp X)   (print "X is a list"))
  ((stringp X) (print "X is a string"))
  (t           (print "X is neither a list nor a string")) )
"X is neither a list nor a string"               ; The side effect of PRINT
==> "X is neither a list nor a string"            ; The value PRINT returns

2. let/let*

This is the method to declare local variables. If you simply use setq on an undeclared variable inside a function, you are assigning to a global variable. This should be completely avoided!

Format:

(let  ( Variable-Declaration* ) 
  Body of Code)
A variable declaration can be either a variable name or a list of variable name and initial value. LET returns the value of the last form in the body of code. The following have identical results:

(let ((X 3) (Y 4) (Z 5))               (let (X Y Z)
  (+ X Y Z))                             (setq X 3)
                                         (setq Y 4)
                                         (setq X 5)
                                         (+ X Y Z))
==> 12

Common bug: when only declaring a single local variable, it is easy to forget the set of parens around the variable declarations. I.e. getting the first below when you intended the second:

(let (X Y) ( ...))   ; This declares two local vars X and Y, initializing neither
(let ((X Y)) (...))   ; This declares X as a local var, initializing it with the value of Y

If you supply initial values, let allows the compiler to do the assignments in parallel, and thus one local variable cannot depend on a previous one. If you want it to, use let*.