2 Booleans and Conditionals
type
> (if t 1 2) 1
> (cond (t "a") (t "b")) "a"
Warning: t happens to be both a boolean and a symbol, so be careful when mixing symbols with booleans.
> (booleanp t) t
> (symbolp t) t
> (if nil 1 2) 2
> (cond (nil "a") (t "b")) "b"
Warning: nil happens to be a boolean, a list, and a symbol, so be careful when mixing lists with booleans, symbols with booleans, or lists with symbols.
> (booleanp nil) t
> (symbolp nil) t
> (tlp nil) t
> (booleanp t) t
> (booleanp nil) t
> (booleanp 5) nil
> (booleanp "watermelon") nil
syntax
(if question-expr then-expr else-expr)
> (if t 1 2) 1
> (if nil 1 2) 2
It evaluates the two branches lazily, meaning it doesn’t evaluate then-expr unless the question really is t, and it doesn’t evaluate else-expr unless the question really is nil. So this division-by-zero expression never gets evaluated.
> (if nil (/ 1 0) "the-other-thing") "the-other-thing"
> (if t "the-first-thing" (/ 1 0)) "the-first-thing"
This makes if (and similar forms like cond) useful for guarding function calls against bad data.
> (defunc try-/ (x y) :input-contract (and (rationalp x) (rationalp y)) :output-contract t (if (not (equal y 0)) ; this division is only evaluated when y isn't 0 (/ x y) nil)) > (try-/ 2 6) 1/3
> (try-/ 2 0) nil
This delay in evaluating the branches is also important for functions that use recursion, so it doesn’t evaluate the recursive call when it should be on the base case.
> (cond (nil 1) (t 2) (t 3)) 2
> (cond (nil 1) (nil 2) (t 3)) 3
Like if, cond evaluates its answer expressions lazily, which means it can be used to guard against bad data, or to guard recursive calls.
> (cond (nil (/ 1 0)) (t "the-other-thing")) "the-other-thing"
> (cond (t "the-first-thing") (t (/ 1 0))) "the-first-thing"
> (defunc try-/ (x y) :input-contract (and (rationalp x) (rationalp y)) :output-contract t (cond ((not (equal y 0)) ; this division is only evaluated when y isn't 0 (/ x y)) (t ; else nil))) > (try-/ 3 6) 1/2
> (try-/ 3 0) nil
syntax
(and conjunct-expr ...)
> (and t t) t
> (and t nil) nil
> (and nil t) nil
> (and nil nil) nil
> (and t t t t t) t
> (and t t t nil t) nil
Like if and cond, and evaluates its arguments lazily, only when all of the previous arguments have praduced t. So this division by zero expression never gets evaluated:
> (and nil (/ 1 0)) nil
syntax
(or disjunct-expr ...)
> (or t t) t
> (or t nil) t
> (or nil t) t
> (or nil nil) nil
> (or nil nil nil nil nil) nil
> (or nil nil nil t nil) t
Like if and cond, or evaluates its arguments lazily, only when none of the previous arguments have praduced t. So this division by zero expression never gets evaluated:
> (or t (/ 1 0)) t
> (not t) nil
> (not nil) t
syntax
(implies ante-expr conseq-expr)