The Scheme Programming Language

Scheme was originally designed at M.I.T., where it was quickly put to use as a teaching language for undergraduate computer science courses. Scheme has always been aimed at a different language niche than Common Lisp. In particular, Scheme's designers have focused on keeping the core language as small and as simple as possible. This has obvious benefits for a teaching language and also for programming language researchers who like to be able to formally prove things about languages.

It also has the benefit of making it relatively easy to understand the whole language as specified in the standard. But, it does so at the cost of omitting many useful features that are standardized in Common Lisp. Individual Scheme implementations may provide these features in implementation-specific ways, but their omission from the standard makes it harder to write portable Scheme code than to write portable Common Lisp code.

Scheme also emphasizes a functional programming style and the use of recursion much more than Common Lisp does. If you studied Lisp in college and came away with the impression that it was only an academic language with no real-world application, chances are you learned Scheme. This isn't to say that's a particularly fair characterization of Scheme, but it's even less applicable to Common Lisp, which was expressly designed to be a real-world engineering language rather than a theoretically pure language.

If you've learned Scheme, you should also be aware that a number of subtle differences between Scheme and Common Lisp may trip you up. These differences are also the basis for several perennial religious wars between the hotheads in the Common Lisp and Scheme communities. I'll try to point out some of the more important differences as we go along.

A Brief Introduction to Scheme

Syntax

An expression is an atom or a list. A list consists of a opening (left) round bracket, a number of expressions and a closing (right) round bracket. Atoms can be symbols, numbers, strings or other special types like functions, hash tables, arrays, etc.

Comments are started by a semicolon and run until end of line.

Semantics

All expressions can be evaluated.

Lists are evaluated as function calls. When evaluating a list all the members of the list are evaluated first then the first item (a function) is called with the remaining items in the list as arguments.

Atoms are evaluated depending on their type: symbols are evaluated as variables returning their values. Numbers, strings, functions, etc. evaluate to themselves. The single quote (') prefix prevents evaluation.

Examples and What their Evaluation Returns

scheme> (+ 2 3)
5

scheme> (set! a 4)
4

After setting a to 4:

scheme> (* 3 a)
12

Defining add:

scheme> (define (add a b) (+ a b))
#<CLOSURE (a b) (+ a b)>

Using newly-defined add:

scheme> (add 3 4)
7

Defining a list:

scheme> (set! alist '(apples pears bananas))
(apples pears bananas)

Retrieving the head of a list

scheme> (car alist)
apples

Retrieving the tail of a list

scheme> (cdr alist)
(pears bananas)

Prepending an element to those of a list:

scheme> (set! blist (cons 'oranges alist))
(oranges apples pears bananas)

Joining the elements of a list (into a new one):

scheme> (append alist blist)
(apples pears bananas oranges apples pears bananas)

scheme> (cons alist blist)
((apples pears bananas) oranges apples pears bananas)

scheme> (length alist)
3

scheme> (length (append alist blist))
7