Introduction 2 Lisp Part III Andreas Wichert LEIC-T (Página da cadeira: Fenix) (I) Home Work (II) Data Types and Generic Programming (III) Lisp is Science (IV) Lisp Macros (V) More about Common Lisp an AI 1
(I) Home Work n (1) Construir uma nova lista que corresponde a juntar duas listas [2]> (setf list1 '(a b c)) (A B C) [3]> list1 (A B C) [4]> (setf list2 '(1 2 3 4)) (1 2 3 4) > (rest list1) (B C) [9]> (rest list2) (2 3 4) [10]> (first list1) A [11]> (null list1) NIL [12]> (null '()) T 2
n (junta list1 list2) n (A B C 1 2 3 4) [6]> (trace junta) ;; Tracing function JUNTA. (JUNTA) [7]> (junta list1 list2) 1. Trace: (JUNTA '(A B C) '(1 2 3 4)) 2. Trace: (JUNTA '(B C) '(1 2 3 4)) 3. Trace: (JUNTA '(C) '(1 2 3 4)) 4. Trace: (JUNTA 'NIL '(1 2 3 4)) 4. Trace: JUNTA ==> (1 2 3 4) 3. Trace: JUNTA ==> (C 1 2 3 4) 2. Trace: JUNTA ==> (B C 1 2 3 4) 1. Trace: JUNTA ==> (A B C 1 2 3 4) (A B C 1 2 3 4) n (2) Construir uma func aõ que inverte uma lista usando processo recursivo 3
n Case 1: list1 is nil. The reversal of list1 is simply nil. The result of appending A to the end of an empty list is simply help itself. 4
n Case 2: list1 is constructed by cons. n Now list1 is composed of two parts: (first list1) and (rest list1). n Observe that (first list1) is the last element in the reversal of list1. n If we are to append help to the end of the reversal of list1, then (first list1) will come immediately before the elements of help n Observing the above, we recognize that we obtain the desired result by recursively appending (cons (first list1) help) to the reversal of (rest list1). 5
(II) Data Types and Generic Programming 6
Optional n Common Lisp allows functions to be defined as having optional arguments by placing the keyword &optional before the lambda variables that are to be bound to the optional arguments n The optional arguments are missing in a particular form, the lambda variables are bound to nil Optional 7
&key n You may define your own functions to have keyword parameters by including &key n Keyword arguments that are not supplied default to nil Arrays with several Dimensions (setf exemplo2 (make-array '(2 3) :initial-element :b)) #2A((:B :B :B) (:B :B :B)) > (setf exemplo3 (make-array '(4) :element-type 'bit :initial-contents '(0 1 0 1))) #1A((0 1 0 1)) > (setf exemplo4 #2A((1 2 3) (4 5 6))) #2A((1 2 3) (4 5 6)) ;Selectores: aref, array-dimensions, array-dimension > (aref exemplo4 1 2) 6 > (array-dimensions exemplo4) (2 3) 8
Common Lisp Structures 9
Reduce n One particularly useful generic sequence function is reduce n The reduce function allows you to iterate through a sequence and distill it down into a single result. Generic n Great benefit of the reduce function is that it is generic, as is true for all these sequence functions n It can reduce lists, arrays, or strings in exactly the same way, 10
n Find the largest even number in the list n We are using lambda n The first argument is the largest even number we ve found so far n The second argument is the next number from the list n If the latest number is better than the previous best, we return it n Otherwise, we return the previous best n We pass an explicit initial value to the reduce function by passing in a keyword parameter named :initial-value 11
n Great benefit of the reduce function is that it is generic, as is true for all these sequence functions n It can reduce lists, arrays, or strings in exactly the same way, (II) Lisp is Science 12
n Lisp s main claim to fame is as an academic tool, appropriate for tackling the most complicated scientific problems n Functional programming is a style of programming where we write all of our code using functions. 13
n Fundamental programming-like algebra developed back in the 1930s by Alonzo Church (1903 1995) n In the lambda calculus, you run a program by performing substitution rules on the starting program to determine the result of a function. n The purpose of the function is to do nothing other than to return a result. Functional Style (I) n The function always returns the same result, as long as the same arguments are passed into it. (This is often referred to as referential transparency.) n The function never references variables that are defined outside the function, unless we are certain that these variables will remain constant 14
Functional Style (II) n No variables are modified (or mutated, as functional programmers like to say) by the function n The purpose of the function is to do nothing other than to return a result n The function doesn t do anything that is visible to the outside world, such as pop up a dialog box on the screen Functional Style (III) n The function doesn t take information from an outside source, such as the keyboard or the hard drive n Example: n > (sin 0.5) 0.47942555 15
Side Effect n Whenever a piece of code does something that is visible to the outside world, such as display a dialog box on the screen, we say that the code causes a side effect. n Functional programmers think of such side effects as making your code dirty. Imperative Code n The technical term for such dirty code that contains side effects is imperative code. n The term imperative implies that the code is written in a cookbook style, where you basically say things like first do this, and then do that. n Imperative code is the opposite of functional code 16
Two Parts n You should break your program into two parts n The first, and biggest part, should be completely functional and free of side effects. This is the clean part of your program. n The second, smaller part of your program is the part that has all the side effects, interacting with the the outside world. This code is dirty and should be kept as small as possible. n If a piece of code pops up a dialog box, for example, we deem it dirty and banish it to the imperative section of our code n Things like dialog boxes are not really math, and we shouldn t let them play with our math functions and other clean, functional code 17
Example 18
[4]> (main-loop) Please enther the name of a new widget:apple The database contains the folowing: (APPLE) Please enther the name of a new widget:alfa-romeo The database contains the folowing: (ALFA-ROMEO APPLE) Please enther the name of a new widget:vespa The database contains the folowing: (VESPA ALFA- ROMEO APPLE) Please enther the name of a new widget: Code Composition n Programming should make it easy for you to take different pieces of code and use them together to solve a task n Higher-order programming, which lets you use functions that accept other functions as parameters 19
n Code composition can be a challenge to a beginning functional programmer n Suppose we want to add two to every number in the following list n To do this, we will need to write code to traverse the list, as well as write code to add two to a number n One possible nai ve (and imperative) way 20
n Code structured like this is potentially very efficient n It destroys the original list n We needed to create a variable n Functional Style n There is no longer a clear delineation between the code that adds two to items in the list and the code that traverses the list 21
Higher-Order Programming (IV) Lisp Macros n Suppose, for example, that your program needs a special add function n Why do you need so many parentheses to declare your variable x? 22
n However, you can t just write a regular function to hide those parentheses, because the let command can do things a regular Lisp function can t support n The let command is a special form. n Macros let us get rid of the superfluous parentheses. Let s create a new macro named let1: n Like a function, it has a name (in this case, let1) and arguments passed to it 23
24
This magic wand is called macro expansion Macro Expansion n Macro Expansion, a special transformation that your code is put through before the core of the Lisp interpreter/ compiler gets to see it. n The job of the macro expander is to find any macros in your code (such as our let1 macro) and to convert them into regular Lisp code. 25
n A macro, runs before the program does, when the program is read and compiled by your Lisp environment. n This is called macro expansion time. n When we define a new macro with the defmacro command, we re basically teaching the Lisp macro expansion system a new transformation that it can use to translate code before running a program. n The first line of this defmacro tells the macro expander, n Hey, if you see a form in code that begins with let1, here s what you need to do to transform it into standard Lisp. 26
n The let1 macro has three such arguments passed into it: var, val, and body n Hey, if you see a form in code that begins with let1, here s what you need to do to transform it into standard Lisp. n var The first argument is the name of the variable we re defining. n val The second expression holds the code that determines the value of the variable n body The third expression inside a let1 call is the body code, which makes use of the new variable that s created 27
n The let command is allowed to have multiple statements in its body n This is why, in the defmacro command defining let1, the final body argument has the special keyword &body in front of it. n This tells the macro expander Give me all remaining expressions in the macro in a list. 28
Dangers n Macros allow us to write code that generates other code n They let you trick the Lisp compiler/ interpreter into accepting your own customized n The main drawback of macros is that they can make it hard for other programmers to understand your code 29
(V) More about Common Lisp an AI n The Minimax Algorithm n Chapter 15 in LoL http://aima.cs.berkeley.edu 30