Variables

Variables

Robbert Haarman

2010-12-11


Introduction

Variables in Scheme can be used to hold values of any type. One variable can hold values of different types during its lifetime. This part of the tutorial describes how variables are declared and used in Scheme.


Define

One way to declare variables in Scheme is using define. It takes two arguments: the name of the variable to define, and its value. define adds the variable to the top-level environment, so that it can be seen from anywhere.

Define can also be used for defining functions. The following syntax can be used for this:

(define (name arguments) body)

Here, name is the name of the function you are defining, arguments are zero or more argument names, and body is a sequence of expressions. The function must be called with values for each of the arguments, and will evaluate the expressions in the body, returning the value of the last expression. The arguments are variables that are only visible inside the function, and they will eclipse any variables outside the function that have the same name.

An example:

; A simple variable
(define foo 12)

; A function with no arguments that references foo
(define (print-foo) (display foo) (newline))

; A function that prints the sum of its two arguments
(define (print-sum a b) (display (+ a b)) (newline))

; A function that prints its argument
(define (print-arg foo) (display foo) (newline))

(print-foo)
(print-sum foo 1)
(print-arg "bar")
(print-foo)

The output of this program is:

12
13
bar
12

Evidently, foo has the value "bar" inside print-arg, but 12 outside of it. This is because foo inside and foo outside are really two different variables. They just happen to have the same name.


Let

Another way of declaring variables is by means of let. Contrary to define, let does not add variables to the top-level environment. Instead, variables are only visible inside the body of let. It has the following syntax:

(let (declarations) body)

The declarations part consists of declarations of the form (symbol value). The body contains normal Scheme expressions. They will be evaluated in order, and let will return the value of the last expression evaluated. Let's see some examples:

(let ((a 1) (b 2)) (+ a b)) ; => 3

; Tell the user something he already knows:
(let ((a "You typed: ") (b (read-line)))
	(display (string-append a b))
	(newline))

Let*

Note that variables defined by let are defined only in the body. You might expect the following code to return 3:

(let ((a 1) (b (+ a 1))) (+ a b))

More likely, an error will be signaled in the definition of b, because a is not defined yet. That is, unless a had been defined outside the let, in which case b will get the value of that definition, plus one. You can rewrite the code above to actually return 3 by using a variant of let called let*. It works like let, but defines the variables in order of appearance. a will be defined and bound to 1 when the definition for b is processed, so b gets the value 2, the body is evaluated, and the value 3 is returned.


Letrec

Yet another variant of let is letrec. It differs from the others in that it first defines all variables, and then starts assigning values. This means that you can reference any of the other variables in the definition of a variable. This can be used for defining mutually recursive functions (functions that call one another). See Binding constructs in the Report for an example.

Valid XHTML 1.1! Valid CSS! Viewable with Any Browser