# Messiaen Quartet for the end of time And another.

## Presentation on theme: "Messiaen Quartet for the end of time And another."— Presentation transcript:

Messiaen Quartet for the end of time And another

Now for the fun (hard) part Recursion Necessary to work on LISTS of data where we want to affect each element of the list as in (add-one (1 2 3 4)) (2 3 4 5)

Recursion Lisp is widely known for its use of recursion, functions that call themselves during execution with lesser and lesser elements of their arbitrary-length list arguments. Using recursion therefore means that users need not know the actual length of list arguments in order to access them, a great advantage when manipulating vast amounts of information.

The following code describes a user- defined recursive function also called add-one that adds 1 to each of the elements in its list argument. (defun add-one (list-of-numbers) (if (null list-of-numbers) () (cons (+ 1 (first list-of-numbers)) (add-one (rest list-of-numbers)))))

How it works: (line 1) the first line of code names the function and declares the variables that will represent its argument(s) in a list (in this case only one named argument exists). (defun add-one (list-of-numbers)

Continue (line 2) the function if in this case tests the argument list-of-numbers to ascertain if it contains data, and if empty it then returns an empty list (second line of code) (if (null list-of-numbers) ()

Continue (line 3) if (else) the list still contains entries, the code constructs a list consisting of 1 added to the first of add- one's list argument (cons (+ 1 (first list-of-numbers))

Continue (line 4) the result of add-one's application to the remainder of the list. (add-one (rest list-of-numbers)))))

Here we go again: (defun add-one (list-of-numbers) (if (null list-of-numbers) () (cons (+ 1 (first list-of-numbers)) (add-one (rest list-of-numbers)))))

Note The terminating code (or second line) in the definition of add-one must occur first, because if the function add-one were to attempt to add 1 to an empty list, it would fail (since (), read also as nil, is not a number in its final recursive call).

Note The terminating code (or second line) in the definition of add-one must occur first, because if the function add-one were to attempt to add 1 to an empty list, it would fail (since (), read also as nil, is not a number in its final recursive call).

What really happens (cons (+ 1 1 ) (cons (+ 1 2 ) (cons (+ 1 3) ()))) Where the last empty parentheses acts as the empty list in which all the remainder of the numbers are placed.

Again Lets try it all over again

Recursion The ability of a function to call itself on lesser and lesser amounts of its argument until the argument is empty.

Begin (defun add-one (list-of-numbers) Looks pretty much like before, but remember that the variable list-of-numbers is going to be a list that we will want to add one to each of its elements.

Hard part We know that if we call the function over and over again it will finally find an empty list and if we try to add 1 to nil well get an error. Thus the first thing we want to do is to make sure we have a default way to escape the recursion.

(defun add-one (list-of-numbers) (if (null list-of-numbers) nil What this does is if the list is empty, then we want it to return nil or an empty list. This will become clear when we finish the function.

Heres where cons comes in handy (defun add-one (list-of-numbers) (if (null list-of-numbers) () (cons (+ 1 (first list-of-numbers)) We collect the first of the list altered by adding one to it.

And now (defun add-one (list-of-numbers) (if (null list-of-numbers) () (cons (+ 1 (first list-of-numbers)) (add-one (rest list-of-numbers))))) Were done and time to review the process. Especially the last line where the recursion is.

Recursion (defun add-one (list-of-numbers) ;;;name the fcn and arg (if (null list-of-numbers) () ;;;ensure no mistake (cons (+ 1 (first list-of-numbers)) ;;;cons add (add-one (rest list-of-numbers))))) ;;;recurse Note how each time the function recurses, it does so without its first element. Slowly this moves down the list until its nil when the conditional if saves us from adding a number (1) to a nil (error!!!!).

Pretend We have (add-one (1 2 3)) Then it works like this: (cons (+ 1 1 ) (cons (+ 1 2 ) (cons (+ 1 3) ()))) (defun add-one (list-of-numbers) ;;;name the fcn and arg (if (null list-of-numbers) () ;;;ensure no mistake (cons (+ 1 (first list-of-numbers)) ;;;cons add (add-one (rest list-of-numbers))))) ;;;recurse To give us (2 3 4) The empty list at the end of the above is in line 2 of the function definition.

Yet another way to look at it: Imagine a cylinder You grab a number from the list, add one to it, then Push it into the cylinder. Continue doing this until you reach an empty list. Then use the empty list and pull the added-numbers out one by one (backwards) and put them into the empty list (backwards) and you end up with the riginal list. The cylinder is called a stack in computerize.

Whew Basically we are done. There are a few things that we will need to learn (other primitive names, alternative ways to do things, save midi files, etc.) but this is pretty much it. On the other hand, you will have to REALLY get this in your blood. PRACTICE……

Assignment Write a normalization function. Normalization is bringing numbers within a particular range. For example, if we have a number that occurs in a range of 1-1000 we might want to make it a pitch (midi pitches for us will be 24 to 96). 500 in the first range would therefore be 60 in the second range. Now, what if we had a whole bunch of numbers in the 1- 1000 range. We will need a function that will place all of these numbers in our midi range.

You will need two functions: 1) you will need a function that will normalize a single number; and then 2) youll need another function that will run the above function through the entire list of numbers. The result will be a new list of normalized and and thus playable midi notes. We will make music with this next Monday. Everyone will make a piece next week!!!!!

Remember to DIVIDE AND CONQUER No great math is needed, just patience and LOGIC.

I am at howell@ucsc.edu, so if you really have problems, send me your code an d/or questions.howell@ucsc.edu,so OR do you want to set up the email chat list now?????????

Also, check out the new exercises on the class website.

Final projects One more week to figure these out?

Next week We will all create our own works in class and play them for one another!