David Cope and Experiments in Musical Intelligence: Lisp

David Cope’s preferred programming language, with which EMI continues to be programmed since the early 1980’s, was first defined in 1958 under the direction of John McCarthy at the Massachusetts Institute of Technology (MIT). Lisp is a high-level interpreted computer programming language remaining today as the earliest functional programming language, the oldest programming language still in use, and as the lingua franca for the field of artificial intelligence (AI) (Tanimoto 1987). A high-level computer language differentiates itself from an assembly language by providing built-in functionality such as declarations, control statements, automated memory management, etc. All these processes, contribute significatively to the performance of complex computations using a rather reduced number of instructions.
An interpreted language translates a program (source code) into machine (or object) code following the flow of written instructions statement by statement. The contrasting approach is the compiled language type, such as in Fortran, C or Pascal languages, in which all instructions are translated at once to machine level.
The word Lisp stands for its own structural principle, List Processing, where the elements of linked lists are connected in the machine’s address space by pointers (rather then proximity), thus allowing far more flexible data structures.
Lisp was created for the processing and manipulation of structured symbolic information in an interactive environment (Harrison 1990). The user types expressions in the front-end (listener window) which evaluates them and replies by printing a value followed by a top-level prompt, letting the user know that the system is ready for another request. The top level prompt may appear signaled differently according to the Macintosh Common Lisp implementation in use. In conformity with Cope’s own texts, I’ll adopt here > as the symbol for the top level prompt.
An example of a dialogue between the user and Lisp would be to ask the system to print the value of the integer 7. The user types the given integer on the listener window after the prompt, presses the carriage return to evaluate the request, and the resulting value is immediately printed, followed by one more prompt signaling the system’s availability to accept another user inquiry:

> 7
7
>

Despite the infinite combinatorial possibilities of symbolic expressions in Lisp (hereafter s-expression), every legal s-expression in a Lisp program and data statements belongs to one of the two possible and mutually exclusive Lisp types of structure. With one exception, all legal Lisp’s s-expressions are either atoms or lists. The exception is NIL, as will be explained ahead, can be both an atom and a list.
An atom is an s-expression that can be either numerical or literal. Numerical atoms have permanent values, meaning that, a number always represents itself as the value of 7 always remains 7. Literal atoms can be made into variables and symbolize any given value. Two exceptions to note are NIL and T that, similarly to numerical atoms, have permanent value, where T always equals to T (boolean value for true) and NIL to Nil (the boolean value for false):

> t
T
> nil
NIL

A list, an ordered collection of n elements, is an s-expression delimited by a matching number of left and right parenthesis. Every list carries content. A list’s content is described by the elements inside. These elements can be atoms or other lists (i.e., nested lists) or a combination of both. In case of an empty list, such list appears represented as () or as NIL. As above mentioned, NIL has the exceptional quality of being simultaneously an atom and a list. That is, NIL, the literal atom that represents the empty list is a list itself. The content represented inside the bounding parenthesis of a list can enclose collections of data elements, a function’s definition, a function call or it may be left empty. Here follow some examples of Lisp’s structures:

COPE - a literal atom
EMI  - a literal atom
2003 - a numerical atom
5/3 - a numerical atom
(compose a (analyze b)) - a list of S-expressions
() - an empty list
NIL - a literal atom and an empty list

Lisp protocols impose specific syntactic roles to the elements of a list according to their position inside the list. The first element following a left parenthesis, unless preceded by a single quote, should be a function. Functions are instructions for manipulation of data (atoms or lists). If the first element is indeed preceded by a single quote then that element is data and not a function.

(function-x ‘data-1 ‘data-2)

The remaining elements following the function and prior to the right parenthesis
are data:

> (+ 1 3)
4

Arguments that are themselves expressions are evaluated first. In the next example
the asterisk means multiplication and the slash means divide, so that this expression
equals to 25 - 1:

> (- (* 5 5) (/ 2 2))
24

Strings, just as numbers and the boolean constants T and NIL, evaluate to
themselves:

> "this is a string!"
"this is a string!"