Variables

You can declare a variable using a ! form. This takes a variable name, and an expression. It declares a new variable with the given name, and gives it the value of the expression.

#|kawa:1|# (! binary-kilo 1024)
#|kawa:2|# (! binary-mega (* binary-kilo binary-kilo))
#|kawa:3|# binary-mega
1048576

If you prefer, you can use define instead of !:

#|kawa:1|# (define binary-kilo 1024)
#|kawa:2|# (define binary-mega (* binary-kilo binary-kilo))
#|kawa:3|# binary-mega
1048576

The advantage of using define is that it is portable to other Scheme implementations. The advantages of using ! is that it is shorter; it generalizes to patterns (see later); and it guards against accidentally “shadowing” a variable by a nested variable with the same name.

A ! (or define) typed into the command-line defines a top-level variable.

You can also declare local variables, which are variables defined for a given block of code. For example, in the following code let is used to set up a local binding of x to 3: this does not affect the outer binding of x to 5:

(define x 5)

(let ((x 3))
  (display x))  ⇒ 3

(display x)     ⇒ 5

Alternative forms for defining local variables are let, let*, or letrec/letrec*.

The differences are in the order in which definitions are made. let evaluates all its definitions in the environment holding at the start of the let statement. In the following example, the local variables are defined using values from the global variables:

(define x 5)
(define y 2)

(let ((x (+ 2 y))  ; uses value of global y, i.e. 2
      (y (+ 3 x))) ; uses value of global x, i.e. 5
  (display (list x y)))  ⇒ (4 8)

let* instead evaluates each definition in the environment holding at the start of the let* statement, along with all previous local definitions. In the following example, y is now defined with the local value of x:

(define x 5)
(define y 2)

(let* ((x (+ 2 y))  ; uses value of global y, i.e. 2
       (y (+ 3 x))) ; uses value of local x, i.e. 4
  (display (list x y)))  ⇒ (4 7)

letrec/letrec* are similar, but allow the definition of recursive functions:

(letrec ((is-even? (lambda (n) (and (not (= 1 n))
                                    (or (zero? n)
                                        (is-odd? (- n 1))))))
         (is-odd? (lambda (n) (and (not (zero? n))
                                   (or (= 1 n)
                                       (is-even? (- n 1)))))))
  (display (is-even? 11)))   ⇒ #f