Scheme Programming/A taste of Scheme

Now that we have an idea of how to run a Scheme interpreter, let's see what we can do with it in some short examples. We won't consider these programs in any depth. For now, the intention is to give the reader a feel for Scheme.

A Scheme interpreter evaluates Scheme expressions typed by the user. With our interpreter running, we first evaluate a very simple expression.

When we enter '4' and hit Enter, we are asking our Scheme interpreter to evaluate the expression '4'. Unsurprisingly, 4 evaluates to 4.

Next, we try some basic arithmetic.

These examples illustrate some important things about Scheme syntax. First, the syntax is fully-parenthesized; the parentheses in the above expressions are required, and extra parentheses cannot be added without changing the meaning of the expression. For example, the following causes the interpreter to report an error:

Secondly, we see that Scheme uses prefix notation. In each expression, the operator (+, *, -) comes before the operands (the numbers). This is unlike the usual ("infix") convention of mathematical notation, in which the operator is written between the operands. For example, the following isn't a valid Scheme expression:

It's easy to translate it into Scheme, however:

Notice that here we've used the expression  as an operand of another expression! This is valid Scheme, and we will see such nested expressions everywhere.

Scheme allows us to name values for use in other expressions:

The definition  causes the interpreter to define   to mean the value. When appears in code following the definition, it will be replaced by this value. We can then use  in the definition of.

We can also define procedures. Like the built-in operators ,, etc., a procedure takes a certain number of parameters (also known as arguments) and computes a value.

Here, we have defined  to mean a procedure taking one parameter,, and returning the value of. The form of this definition is a little different from those we saw earlier; here, the name being defined appears in parentheses, followed by the names of the procedure's parameters. To use this newly-defined procedure, we evaluate.

Here's a more complex procedure which calculates the area of a triangle with sides $$a$$, $$b$$, and $$c$$ using Heron's formula:

In this procedure, we need to use the value $$s$$, defined by


 * $$s = \frac{a + b + c}{2}$$,

four times. The definition of  would be tedious to write and hard to read if we were to use for each occurrence of $$s$$. We solve this problem using the form, which allows us to temporarily associate the name with this value.

We can compare values, or test them for certain properties.

What are the  and   values which Scheme gives us back here? As you may have guessed, these are boolean values representing "true" and "false", respectively.

Predicates like  are procedures which take one argument and return a boolean value. It's a Scheme convention to give predicates names ending with '?'; hence we have , , and many others.

Procedures can be recursive. Here's a classic example.

Evaluating  gives us the value of $$5!$$, that is, $$5 \times 4 \times 3 \times 2 \times 1$$, which we can express recursively as $$5 \times 4!$$. More generally, we say that factorial of $$n$$ is 1 if $$n$$ is zero, and $$n$$ times the factorial of $$n - 1$$ otherwise. This is precisely what the definition of  states in the language of Scheme:

Recursion is a critical notion in Scheme (and in computer science in general) that we will discuss in greater depth in later sections.

Another new thing in the definition of  is the use of the   form, which evaluates its first argument, then either its second or third argument depending on whether the first was true or false. If the first argument evaluates to true, then we get the second argument of the  form; otherwise, we get the third.