ArsDigita University, Structure and Interpretation of Computer Programs

Lecture Notes for Lecture 1 -- 1 October 2000

Topics covered in today's lecture:

How does this course fit inot the ADU curriculum?

This course is the first programming course at ADU, taught in Scheme. Scheme is a useful language for an intro class because we can teach you about its syntax in a very short time (in fact, in this lecture alone) and you can start writing programs immediately. Scheme allows us to focus on concepts rather than syntax.

Looking at the upcoming courses at ADU, here are some ways that the material in this class applies to the upcoming courses:

Additionally, we'll touch on compilers in this course. Compilers are not in the ADU curriculum, but it's good to understand how one might write a compiler.

Intro to Scheme

Every powerful language has

Scheme does the following three things:

  1. Reads an expression
  2. Evaluates it to produce a value
  3. Prints the value

The returned value has a small set of types, including number, boolean and procedure. (Later, we'll see symbol, pair, vector, and promise (stream).)

There are 4 types of expressions:

  1. Constants: numbers, booleans. Examples: 4 3.141592 #t #f
  2. Variables: names for values. We create these using the special form define
  3. Special forms: have special rules for evaluation. In addition, you may not redefine a special form.
  4. Combinations: (<operator> <operands>). These are sometimes called "function calls" or "procedure applications."

The first two types of expressions (constants and variables) are primitive expressions -- they have no parentheses. The second two types are called compound expressions -- they have parentheses.

Mantras

  1. Every expression has a value (except for errors, infinite loops and the define special form)
  2. To find the value of a combination,
  3. The value of a lambda expression is a procedure

Lambda

When you hear the words "write a procedure," you should think of lambda. Lambda is a special form that creates a procedure. There are three parts to the lambda expression:
  1. lambda
  2. parameter list
  3. body
For example, let's write a procedure to square a number:

(lambda (x) (* x x))

How do we use this procedure that we just wrote? Well, we can write
((lambda (x) (* x x)) 3)

This will return 9.

If we want to square 9, we can write
((lambda (x) (* x x)) 9)

But we don't want to have to keep typing the procedure over and over. This leads us to another special form: define.

Define

Define is a special form that allows us to name objects. Define has three parts:
  1. define
  2. name
  3. the object you want the name to be bound to
Here are some examples:



(define pi 3.141592)

(define four 8)



We can use define to name our procedure we wrote above to allow us to use it without having to retype the lambda expression over and over.

(define square (lambda (x) (* x x)))

Special Forms Have Special Rules

Recall that special forms are those expressions that begin with an open parenthesis followed by one of the 15 "magic words":

and, begin, case, cond, define, do, if, lambda, let, let*, letrec, or, quasiquote, quote, set!

Special forms have special rules for their evaluation. Recall from the mantras that to find the value of a combination, you find the values of all of the subexpressions in any order. With special forms, this is not done. The order of the evaluation of the subexpressions is specified for each special form.


(and <exp1> <exp2> ...)

And evaluates the expressions one at a time in left to right order. As soon as one of the expressions evaluates to #f (false), the value of the and expression is #f (false) and none of the remaining expressions are evaluated.


(or <exp1> <exp2> ...)

Or evaluates the expressions one at a time in left to right order. As soon as one of the expressions evaluates to #t (true), the value of the or expression is #t (true) and none of the remaining expressions are evaluated.


(if <predicate> <consequent> <alternative>)

The predicate is evaluated. If it is true, the value of the consequent will be returned. If it is false, the value of the alternative will be returned. In this special form, never will the consequent and alternative both be evaluated.




(cond (<pred1> <exp1>)

      (<pred2> <exp2>)

      ...

      (else <expn>))



The first predicate is evaluated. If it is true, the value of the first expression will be returned. If it is false, the second predicate will be evaluated. The computer will continue to evaluate the predicates until one is true. The value of the expression corresponding to the true predicate will be returned. Note that the else will always be true.



Written by: Holly Yanco
Last update: 1 October 2000