Conditionals and Predicates
if is the one branching form:
(if condition then else)
Both branches are always present. The condition must evaluate to a
number: 0 is false, anything else is true.
(if 1 'yes 'no)
;=> 'yes
(if 0 'yes 'no)
;=> 'no
(if (- 3 3) 'zero 'nonzero)
;=> 'nonzero
The condition may not be nil, a symbol, or a pair — only numbers
branch (and code values, which residualize the if; Part II):
(if nil 'yes 'no)
;! type error in if: expected Cst or Code, got Nil
This is stricter than most Lisps, where anything non-false is true.
The discipline is inherited from the reference base.scm, and it
composes with the boolean encoding: predicates answer 1 or 0, so
predicates are exactly the things if accepts.
The type predicates
Four predicates classify a value by kind, answering 1 or 0:
(number? 3)
;=> 1
(symbol? 'a)
;=> 1
(null? nil)
;=> 1
(pair? (cons 1 2))
;=> 1
Each answers 0 for everything outside its kind — there is no error
case:
(number? 'a)
;=> 0
(null? 0)
;=> 0
(A fifth, code?, tests for staged code; it takes an extra
stage-dispatch operand and is covered with the rest of the staging
forms in Part II.)
eq?
eq? is the equality test, answering 1 or 0. On numbers, symbols,
and nil it is the obvious comparison; on pairs it is structural,
comparing recursively:
(eq? 'a 'a)
;=> 1
(eq? '(1 (2 3)) '(1 (2 3)))
;=> 1
(eq? '(1 2) '(1 3))
;=> 0
Values of different kinds are unequal, never an error:
(eq? 0 nil)
;=> 0
Closures compare structurally too — two separately written but
identical lambdas are eq?. Cells compare by identity: two cells are
eq? only if they are the same cell, no matter their contents (see
the cells chapter). Code operands do not compare at all — like every
operation on code, the eq? residualizes (Part II), which is how
generated programs get to contain equality tests.
Testing numbers for equality
There is no = primitive; eq? covers numbers. Library code
sometimes exploits the boolean encoding instead — lib/mk.naj defines
its own numeric equality as
(let = (lambda _ a (lambda _ b (if (- a b) 0 1)))
(= 3 3))
;=> 1
reading (- a b) as “true iff a ≠ b”. Arithmetic-as-logic is
idiomatic here.