Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.