# Class 05: Untyped Functional Programming in Scheme

Held Wednesday, February 3

Summary

Contents

## An introduction to LISP-like languages

• LISP (for LISt Processing language) was developed by John McCarthy of MIT in the late 1950's as a language for artificial intelligence programming.
• At the time LISP was developed, many researchers suggested that intelligence involved
• symbolic manipulation and
• organization of symbols in hierarchical structures.
• In developing a language to support ``intelligence'', McCarthy chose to include
• symbols as basic data types (supporting symbolic manipulation);
• built-in heterogeneous lists and list-manipulation operations (permitting the construction and manipulation of hierarchical structures);
• numbers and strings as basic data types (yes, we do math, too); and
• functions as a basic data type (yes, he read Church).
• Noting that the application of a function to arguments is similar to listing the function and its arguments, McCarthy also chose to use the same notation for function applications and list structures.
• An open paren
• The elements of the list (or the function and its arguments), separated by spaces
• A close paren
• For example, consider `(a b c)`.
• In one context, this is the list of three elements, `a`, `b`, and `c`.
• In another context, this is the application of the function `a` to two arguments, `b` and `c`.
• This is an extreme application of von Neumann's assertion that programs are data: in LISP, the same structure can be treated as a list at one point and a function application at another.
• McCarthy chose to use a prefix notation for all function operations, including ``primitive'' operations. In LISP, we write `(+ 2 3)` for ``add two and three''.
• LISP is often interpreted. Most LISP interpreters use the read-eval-print model. That is, the interpreter
• reads an input expression or function definition;
• evaluates the expression; and
• prints the result.
• In LISP, function order is done in applicative (also known as eager or innermost) order: before functions are applied to their arguments, those arguments are evaluated.
• It is often helpful to classify the types of functions we use in writing LISP programs.
• Constructors build data structures.
• The most common constructor is `cons` which builds lists.
• Destructors and Selectors extract components from data structures.
• The most common selectors are `head` which selects the first element of a list and `tail` which selects all but the first element.
• Predicates return boolean values.
• Most predicates check types or attributes of their arguments. For example, `atom?` checks whether something is an atom.
• The power of McCarthy's design is demonstrated by LISP's longevity. LISP and LISP variants are still dominant languages for AI programming (and for other types of programming).

### Lists in LISP-like languages

(How's that for alliteration?)

• Most (all?) LISP-like languages provide a number of functions for building and modifying lists.
• LISP builds its lists with cons cells, pairs of pointers.
• The first pointer gives the data.
• The second pointer gives the rest of the list.
• The empty list is `nil` or `()`.
• The predicate that checks if a list is empty is usually `nullP` (in LISP) or `null?` (in Scheme).
• One constructs lists with `cons`. `(cons x x)` builds a list with first element `x` and remainder `xs`.
• Those of you who like to think about what's happening in memory can think of this as allocating a new cons cell whose left pointer is the object and whose right pointer is the list.
• Those of you who prefer a higher-level view can think of this as a form of ``prepend''.
• In many variants of LISP, one can build longer lists with `list`.
• `(list a b c)` produces the same result as `(cons a (cons b (cons c nil)))`
• You can get the first element of a list with `(car list)`.
• You can get the all but the first element of a list with `(cdr list)`.
• Why `car` and `cdr`? Because in the original machine LISP was implemented on, it was easy to load the cons cell into the address and data registers. ```car`'' is ``contents of address register''. ```cdr`" is "contents of data register''.
• In many LISP-like languages, `car` is called `head` and `cdr` is called `tail`.

## An introduction to Scheme

• Scheme is a variant of LISP that "cleans up" some of the problems of the original LISP.
• Scheme provides
• Static scoping (the original LISP was dynamically scoped).
• A small formal semantics (the original LISP was informally defined; a later formal semantics took hundreds of pages).
• Streams, a form of ``infinite'' lists (which had been suggested as an add-on to the original LISP).
• A way to package up ``the rest of the program''. These are called continuations.
• A host of other features.
• Scheme is now defined by committee. The most current definition is the fifth revision, which has been a few years in the making.
• Scheme provides a number of basic operations
• Mathematics
• More predicates than you can shake a stick at.
• Simple conditionals, such as `(if test then-part else-part)`
• An expanded conditional which bears some resemblance to the guarded conditional (but the guards are executed in order)
```(cond (
(test1 exp1)
(test2 exp2)
...
(testn expn)
))
```
• In Scheme, we define ``global'' variables with `(define id exp)`.
• Similarly, we can define ``global'' functions with `(define (fun param1 ... paramn) exp)`

### Scheme in the MathLAN

• We use a commercial version of Scheme in the MathLAN, Chez Scheme.
• Chez Scheme provides a simple interactive interface which you can get by typing `scheme` at a Unix prompt.

### Some sample scheme stuff

```;;; Compute the factorial of n.
(define (fact n)
(if (= n 0) 1 (* n (fact (- n 1)))))

;;; Add x to the end of list l.
(if (null? l)
(list x)
(cons (car l) (addend x (cdr l)))))

;;; Reverse the list l.
;;; Yes, this function is a standard Scheme function, but it is
;;;   helpful to consider how we might write it.
(define (reverse l)
(if (null? l)
()
(addend (car l) (reverse (cdr l)))))

;;; Here is an attempt to write a more efficient reverse function.

;;; Create the list of the elements of l in reverse order followed
;;; by the elements of r.  For example, (tailrev '(a b c) '(3 2 1))
;;; will create the list (c b a 3 2 1).
(define (tailrev l r)
(if (null? l)
r
(tailrev (cdr l) (cons (car l) r))))
;;; Reverse the list l, using our new helper function.
(define (reverse l)
(tailrev l ()))
```

## Short Lab

We experimented with the functions given above.

History

• Created Tuesday, January 19, 1999 as a blank outline.
• Filled in the details on Wednesday, February 3, 1999. Based primarily on outline 21 from last year's class.
• Removed some details after class.

Disclaimer Often, these pages were created ``on the fly'' with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.