Bab 5. Common Lisp

1. Expressions. Primary data structure of lisp is called s-expression (symbolic-expression) where major categories of expressions are lists and atoms. A list is just a sequence of objects inside a pair of parentheses, and the 1st elemen of the list is an operator, the rest of the list contains arguments of the operator. → (* 8 3) 24 → ; (* 8 3) is supplied arguments and 24 is actual arguments

→ (* (+ 8 3) (+ 4 (* 9 2))) 242 → 8 8 → (1+ 8) 9 → (+ 7 8 9) 24 → (1+ 8 9) Error: Debug1>: quit

2. Symbols. → (setq x 5) 5 → x 5 → (+ x 8) 13 → x 5 → (setq x ( + 4 5)) ; using symbol as argument to function not change its value 9 → x 9 → (+ 2 (setq x ( * 3 4))) 14 → x 12 → (setq 1+ 17) 17 → 1+ 17 → (1+ 3) 4 → ()

Assigning 1+ a value has no effect whatsoever on its role as a function name. Symbols serve the dual roles of function identifiers and variable specifiers. The term atom refers to any lisp object that is not viewed as having parts (numbers and symbols are atoms while lists are not).

3. Lists. ((a b c)) is a list of one element, list (a b c) while (a b c) is a list of three elements, symbol a, b and c. (a b) and (b a) is two different list with the same length 2. (((x))) is also list with length 1. → (a b c) error: 1>: (reset) → (quote (a b c)) (A B C) → '(a b c) (A B C) → 'a A → '6 6 → (setq x '(a b c)) ; lisp is not case sensitive and it always into uppercase (A B C) → x (A B C) → (setq a 'a) A → a A → (setq x 'y) Y → x Y → (set 'x 'z) Z → y Z → x Y

4. List Operations. Symbolic operation on lists consist of taking apart and building them up with two basic functions car and cdr. → (car '(a b c)) A → (cdr '(a b c)) (B C) → (setq x '(a b c)) ; car and cdr are Non-destructive (A B C) → x (A B C) → (car x) A → x ( A B C) → (cdr x) (B C) → x ( A B C) → (cdr '(a b)) (B) → (car (cdr '(a b))) B → (car '((a b))) (A B) → (car (car '((a b)))) A

2 → (cdr '((a b) (c d))) ((C D)) → (car (cdr (car (cdr '((a b c) (d e f))))) E → (cadadr '((a b c) (d e f))) E → (car (cdr '((a b c) (d e f)))) (D E F) → (cadr '((a b c) (d e f)))) (D E F) → (cdr '(c)) NIL →

Setq NIL to something will cause an error. Objects like NIL whose value can not be changed sometimes referred to as constants.

→ (cons 'a (b c)) ; Car and cdr take list apart, CONS builds list up. (A B C) → (cons '(a b) '(c d)) ((A B) C D) → (cons 'a (cons ' b '(c d))) (A B C D) → (setq x '(a b)) (A B) → (cons (car x) (cons (cadr x) '(c d))) (A B C D) → (cons 'a nil) (A) → (cons 'a (cons 'b (cons 'c nil)))) ; cons is a Non-destructive (A B C) → (cons 'a (cons (cons 'b (cons 'c nil)) cons 'd nil))) (A (B C) D) → (list 'a 'b 'c) (A B C) → (list 'a '(b c) 'd) (A (B C) D) → (append '(a b) '(c d) '(e f)) (A B C D E F) → sintaks: (list 'arg1 'agr2) (append 'list1 'list2)

5. User-Defined Functions. sintaks: (defun fname (v1 v2 v3 ……vn) (…body of code-1 ….) (…body of code-2 …..) …..)

Function call: (fname arg-1 arg2 …..argn)

→→→ (defun addthree (x) (+ x 3)) ADDTHREE →→→ (addthree 7) 10 →→→ (setq x (addthree 19)) 22 →→→ (addthree (* 4 (1- 7)))

3 27 → → (defun average (x y) (/ (+ x y) 2)) AVERAGE →→→ (addthree 7) 10 →→→ (average (7 21) 14

→→→ (defun xcons (l e) (cons e l)) XCONS →→→ (xcons '(b c) 'a) (A B C)

→→→ (defun list-of-lists (x) (list (list (car x)) (list (cadr x)))) LIST-OF_LISTS →→→ (list-of-lists '(a b) ) ((A) (B)) →→→ (list-of-lists '(1 2) ) ((1) (2)) →→→ (list-of-lists (xcons (cons 'c nil) 'd)) ((D) (C))

6. Formal Parameter. Even though the definition of addthree uses a formal parameter called x, calling addtgree will not cause the value of x to change outside of that function. →→→ (setq x '(a b c)) ; x is formal parameter of function setq (A B C) →→→ (addthree 7) 10 →→→ x (A B C) →→→ (defun squared (y) (* y y)) SQUARED →→→ (defun hyp ( x y) (sqrt (+ (squared x) (squared y)))) HYP →→→ (hyp 3 4) 5.0 ; use both symbol x for 2 functions but lisp doesn't get confused.

Free and bound symbols A symbol used as a variable within a function, but which is not a formal parameter of that function, is said to be free within that function ( ex. sum within sum-average). Symbol that are not free within a function are said to be bound in that function, such as formal parameter of that function. →→→ (defun sum-average (x y) (setq sum (+ x y)) (/ sum 2 )) SUM-AVERAGE →→→ (sum-average 29 13) → 21 →→→ sum → 42 →→→ (sum-average 7 93) → 50 →→→ sum → 100

4 The changes to free symbols are not local to the functions they occur in. This is completely unlike changes to bound symbols(formal parameter) which are strictly local to a function. So, Free symbols are used to communicate between functions, but this is dangerous because it is difficult to anticipate the consequences of such changes. Usually programmer includes a * the beginning and end of free symbol, such as *sum is a free symbol.

Global variables The variable designated by a symbol at the top level of lisp is called a Global variable. Global variables are independent of any function. They can be referred to directly on the top level of lisp and can be referred to using free symbols in any number of different function calls.

Local variables Associated with formal parameter, come into existence with a particular function call, and referred to only by the code of that function, and tend to disappear forever when the function has terminated.

The bound symbols of sum-average x and y cause new local variables to be created each function sum-average is called, these can be referenced only by sum-average and cease to exist when the sum-average has been completed. The free symbol sum of sum-average refers to the same global variable through any number of call sum-average, and can be referred by other functions and by the user talking to the top level of lisp.

How about if the symbol is free in one function A but bound in another function B ? B call A. →→→ (defun sum-average-caller (sum x y) (sum-average x y) sum ) SUM-AVERAGE-CALLER →→→(sum-average-caller 0 55 65) 0 →→→ sum 120

The value of sum inside sum-average-caller was not changed, sum is local to the sum-average- caller so it could not be referenced by any other function. However, sum-average-caller affected the value of sum at the top level. This means, the local variables are truly local to the code in which they appear. The issue of which variable is referenced by the occurrence of a symbol in a program is sometimes refered as scoping. We need only know the function definition to determine the scope of the symbol. Formal parameter normally have lexical/static scoping meaning that they can be referenced only by the code of the function within which they are parameters. Had they had dynamic scoping, then the variables designated by a parameter can be referred to outside their functions. Ex: changing the value of sum in sum-average would have changed the value of sum, the formal parameter of sum-average-caller, had dynamic scoping been in effect, but it would not affect the value of the global variable sum. Variables with dynamic scoping are called special variables and the specification of this variable is through parameter declaration. →→→ (load 'utilities) (load utilities) T →→→

7. Predicates. Predicates are functions that test for various conditions, can be combined into complicated tests using other functions called logical operators. Predicates are just tests, functions that return true indicated by any value other than nil (usually T) and false indicated by nil. →→→ (atom 'a) T

5 →→→ (atom '8) T → (atom '(a b c)) NIL →→→ (atom (cdr '(a b c))) NIL →→→ (atom nil) T →→→ (listp 'a) ; p stand for predicate NIL →→→ (listp '(a b c)) T →→→ (listp (cdr '(a b c))) T →→→ (listp nil) ; in this case nil means () T →→→ (null nil) T →→→ (null 'a) NIL →→→ (null '(a b c)) NIL →→→ (null ()) T →→→ (consp '(a b c)) ; T if it is a list. T →→→ (consp 'a) NIL →→→ (equal 'a 'b) NIL →→→ (equal 'a 'a) T →→→ (equal '(a b c) '(a b c)) T →→→ (numberp 8) T →→→ (numberp 'a) NIL

Others : zerop, oddp, evenp, > and < →→→ (typep 8 'number) T →→→ (memberp 'b '(a b c)) ;return part of the list with the first match (b c) →→→ (memberp 'b '(a b c d e)) (b c d e) →→→ (memberp 'x '(a b c)) NIL →→→ (memberp 'y '(x (y) z)) NIL →→→ (memberp '(a b) '(a b c)) ; because (a b) is not an atom but a list NIL →→→ (defun car-atomp (x) (atom (car (x))) ; user defined predicates CAR-ATOMP : this still error in some cases →→→ (car-atomp '(a b c)) T →→→ (car-atomp '((a) (b) (c))) NIL

6 8. Conditionals. Cond is a special function and can have any number of arguments, which sometimes called cond clauses. Each cond clause consists of a series of s-expressions. The first element of a cond clause is treated as a condition to be tested for, the rest of the clause consists of things to do should the condition prevail. It evaluates the rest of the s-expression in the clause only if the condition evaluates to true. →→→ (setq x '(a b c)) (A B C) →→→ (cond ((listp x) (car x))) A

→→→ (setq x 'y) Y →→→ (cond ((listp x) (car x))) NIL

→→→ (defun car-atomp (x) (cond ((listp x) (atom (car x))))) CAR-ATOMP →→→ (car-atomp '(a b c)) T →→→ (car-atomp 'z) NIL

→→→ (defun cond-example1 (x) ; similar as case of in other languages (cond ((listp x) (cons 'a x)) ((numberp x) (+ 7 x)))) COND-EXAMPLE1 →→→ (cond-example1 '(b c)) (A B C) →→→ (cond-example1 9) 16 →→→ (cond-example1 'z) NIL

→→→ (defun cond-example2 (x) (cond ((listp x) (setq flog 'list) (cons 'a x)) ((numberp x) (setq flog 'number) (+ 7 x)))) COND-EXAMPLE2 →→→ (cond-example2 '(b c)) (A B C) →→→ flog LIST →→→ (cond-example2 9) 16 →→→ flog NUMBER

→→→ (defun cond-example3 (x) (cond ((listp x) (setq flog 'list) (cons 'a x)) ((numberp x) (setq flog 'number) (+ 7 x)) (t (setq flog 'neither) nil))) COND-EXAMPLE3 →→→ (cond-example3 '(b c)) (A B C) →→→ flog

7 LIST →→→ (cond-example3 'z) NIL →→→ flog NEITHER

→→→ (cond (exp11 exp12 exp13 … ) ;each list of expression is one cond clause (exp21 exp22 exp23 …) (exp31 exp32 exp33 …) ….. (expn1 expn2 expn3 …)) the sintaks above, meanslisp evaluate exp11 first, if true continue to exp12 etc but if it returns false/nil, it will skip the rest and start evaluate exp21

→→→ (defun cond-example4 (x) (cond ((listp x) (setq flog 'list) (cons 'a x)) ((numberp x) (setq flog 'number) (+ 7 x)) ((setq flog 'neither)))) ; always return non nil COND-EXAMPLE4 →→→ (cond-example4 '(b c)) (A B C) →→→ flog LIST →→→ (cond-example4 'z) NEITHER →→→ flog NEITHER

→→→ (defun our-adjoin (e l) ; cons elemen only if it is not in the list (cond : as the form "if then else" construct ((member (e l) l) (t (cons e l)))) OUR-ADJOIN →→→ (our-adjoin 'b '(b c)) (B C) →→→ (our-adjoin 'b '(x y z)) (B X Y Z)

It constructs has the sintaks as: (if test then action else action) If it evaluates to not nil, then evaluate then otherwise evaluate else. If else action is omited, then nothing is done, it returns nil. →→→ (defun our-adjoin (e l) (if (member e l) l (cons e l))) OUR-ADJOIN

9. Logical Operators. →→→ (defun even-50-100 (x) (cond ((numberp x) (cond ((evenp x) (cond ((> x 49) ( < x 101)))))))) EVEN-50-100 →→→ (even-50-100 17) NIL →→→ (even-50-100 88) T →→→ (even-50-100 102) NIL

8 Commonly used logical operators are not, and, or. →→→ (not (atom x)) ; the result t or nil → (and (evenp x) (< x 100)) →→→ (or (null x) (numberp x)) →→→ (and (listp l) (numberp (car l))) ; similar w/ (cond ((listp l) (numberp (car l))) →→→ (defun even-50-100 (x) (and (numberp x) (evenp x) (> x 49) ( < x 101))) ;similar as above

10. Iteration. Lisp has several built-in functions that enable user to write an explicit loop. Can be structured or unstructured (using gotos). The functions are do, do*, dolist, dotimes, and prog.

→→→ (defun do-length (I) (do ((II I (cdr II) (sum 0 (1+ sum))) (( atom II) sum))) DO-LENGTH →→→ do-length '(a b c) 3 →→→ do-length 3 0 →→→ do-length '(a (b c)) 2

The first item after do is a list of index variable specifiers, in the case above (II I (cdr II) and (sum 0 (1+ sum)) The first element of each specifier should be a symbol, an index variable that is II and sum. The next element is a form whose value is used to initialization, so the initial value of II is the value of I, that is (a b c) and the initial value of sum is 0. The last element is a form whose value is assigned the index variable each iteration performed ( increment factor). So, the value of II is changed into cdr(II) and the value of sum is added by 1 each iteration. The next item is an exit clause, work similar as cond. In this case, exit clause is test whether II is an atom. Because it is false, it repeat the 2nd iteration with the value of II is cdr(II), that is (b c) and the value of sum is 1, etc.

→→→ (defun do-length (I) (do ((II I) (sum 0)) (( atom II) sum) (setq II (cdr II)) (setq sum (1+ sum)))) DO-LENGTH

In this ex, the repeated forms from the variable specifiers, so do will not automatically change the values of the vars on each iteration. If initialized forms is omited, all values initialized to nil. →→→ (defun do-rev (I) (do ((x I (cdr x)) (res nil (cons (car x) res))) (( null x) res))) DO-REV →→→ (do-rev '(a b c)) (C B A)

Other do statements: 1. Do* works similar as do except the vari is assigned the value of each respective vali or repi before the next one is evaluated. 2. Dolist allows for simple iteration over the elements of a list. Ex: (dolist (var list-val return-val) 3. Dotimes allows for iteration for every integer up to the specified value.Ex. (dotimes (var stop-val return-val) 4. Prog lets you write code that looks more like traditional programming constructs

9

→→→ (defun prog-length (I) (prog ((sum 0)) ; 1st argument is always a list of local var specifiers again : again is atom (cond ((atom I) (return sum))) ; return only used in prog (setq sum (1+ sum)) (setq I (cdr I)) (go again))) : go is only legal inside prog PROG-LENGTH →→→ prog-length '(a b c) 3 →→→ prog-length '(a (b c)) 2

→→→ (defun prog-member (e I) (prog () ; no local var is used label1 (cond ((atom I) (return nil)) (equal e (car I)) (return I)) (t setq I (cdr I)) (go label1 ))))) PROG-MEMBER

→→→ (defun another-prog-member (e I) (prog () label1 (cond ((atom I) (return nil)) (equal e (car I)) (return I)) (setq I (cdr I)) (go label1 ))) ANOTHER-PROG-MEMBER

Note: go and return are also works in do and do* another form of iteration is using loop, where loop takes any number of expression, evaluate repeatedly from left to right and terminate by return. Progl is useful to simulate how stack is works such as: (progl (car stack) (setq stack( cdr stack))) will return the value of 1st element of stack without saving this element temporarily as a value of var. Prog2 is return the 2nd element of stack, etc up to progn. Other function also available such as block, tagbody and return-from.

11. Recursion. No recursive construct in lisp, should be your own. Equivalent with indefinite repetition.

→→→ (defun recursive-length (I) ; the length of a list I (if (null I) 0 (1+ (recursive-length (cdr I)))))

→→→ (defun recursive-member (e I) ; check the membership e in I (and I (or (equal e (car I)) (recursive-member e (cdr I)))))

→→→ (defun recursive-member (e I) ; check the membership e in I (cond ((null I) nil) ; any list left (t (or ((equal e (car I)) ; make the test (recursive-member e (cdr I))))) ; do recursive step

10 →→→ (defun factorial (n) ; function error for n<0 and non-integer (cond ((zerop n) 1) (t (* n ((factorial (1- n)))))) FACTORIAL →→→ (factorial (3) 6

→→→ (defun our-subst (in out struct) ;change every in with out in the struct (if (atom struct) struct (cons (if (equal out (car struct)) in (our-subst in out (car struct))) (our-subst in out (cdr struct))))) OUR-SUBST →→→ (our-subst 'a 'b '((a b c) b c (d c b a))) ((A A C) A C (D C A A)

→→→ (defun our-subst (in out struct) ;change every in with out in the struct (cond ((atom struct) struct) ((equal out (car struct)) (cons in (our-subst in out (cdr struct)))) (t (cons (our-subst in out (car struct)) (our-subst in out (cdr struct)))))) OUR-SUBST

→→→ (defun our-subst (in out struct) ;change every in with out in the struct (cond ((equal out struct) in) ((atom struct) struct) (t (cons (our-subst in out (car struct)) (our-subst in out (cdr struct)))))) OUR-SUBST

Pls check the difference among the three of our-subst function above

12. Property lists. Every symbol can have any number of properties and each property has a property value such as a symbol table has property color: blue, weight: 1 kg, owner: John etc. Remember : A change to a property is not local to a function definition or prog, even if the symbol designates a formal parameter or a local variable. (This uniqueness seems inconsistent. A single symbol may refer to different variables at different times. The same symbol may be used to designate a formal parameter in one place, a prog variable in other places and an index variable somewhere else but all of them has the sama property value ) Getf doesn't expect the first argument to be a symbol with a property list Ex. Database book in the library

→→→ (defun add-book (bookref author publisher) (setf (get bookref 'title) title) (setf (get bookref 'author) author) (setf (get bookref 'publisher) publisher) (setq *library∗∗∗ (cons bookref *library∗∗∗ )) bookref) ADD-BOOK →→→ (setq *library∗∗∗ nil) NIL →→→ (add-book 'book1 '(siti nurbaya)

11 '(marah rusli) '(balai pustaka)) BOOK1 →→→ (add-book 'book2 '(layar berkembang) '(motinggo busye) '(dian press)) BOOK2 → (add-book 'book3 '(algoritma pemrograman) '(ferrianto gozali) '(trisakti university)) BOOK3 →→→*library∗∗∗ (BOOK1 BOOK2 BOOK3) →→→ (defun retrieve-by (property value) (do ((I *library∗∗∗ (cdr I)) (result nil (if (equal (get (car I) property) value) (cons (car I) result) (result))) (null I) result))) RETRIEVE-BY →→→ (retrieve-by 'author '(marah rusli)) (BOOK1)

Property list can be used without any symbols related, and it is very useful as a key. Ex. →→→ (setq list-of-cars '(kuat honda ferry vitara endang kijang saman pajero)) (KUAT HONDA FERRY VITARA ENDANG KIJANG SAMAN PAJERO) →→→ (getf list-of-cars 'saman) PAJERO →→→ (setf (getf list-of-cars 'eli) 'timor) TIMOR

→→→ list-of-cars (ELI TIMOR KUAT HONDA FERRY VITARA ENDANG KIJANG SAMAN PAJERO)

13. Functions as Arguments. In this case we can have function that accepted other functions as arguments.

→→→ (defun sum-of-ints (n) ;find the sum of the 1st n integers (do ((I n (1-I)) (result 0 (+ I result))) ((zerop I) result))) SUM-OF-INTS →→→ (sum-of-ints 5) 15 →→→ (sum-of-ints 10) 55 to have a function that find the sum of the square, or the cube or the square roots of the first n integers, we do not have to write a new function. All these function are similar. So, we write a function as:

→→→ (defun sum-loop (func n) ;find the sum of the 1st func (n) (do ((I n (1-I)) (result 0 (+ (func I) result))) ((zerop I) result))) SUM-LOOP

12

In this case func is meant to be a parameter that will be supplied a function as an argument.

→→→ (sum-loop 'sqrt 5) ;sqr should be a previously defined function 8.382323441762

Lisp provides a set of functions that apply functions under user control using function called apply.

→→→ (apply 'cons '(a (b c))) ;1st argument is a function and 2nd argument is actual (A B C) ; arguments for the function. →→→ (apply '+ '(1 3 5 7)) 16 above examples are exactly like:

→→→ (cons 'a '(b c)) (A B C) →→→ (+ 1 3 5 7) 16 apply doesn't work for special functions such as defun or setq. →→→ (defun sum-loop (func n) (do ((I n (1-I)) (result 0 (+ (apply func (list I) result))) ((zerop I) result))) SUM-LOOP →→→ (defun squared (x) (* x x)) SQUARED →→→ (sum-loop 'squared 5) 55

Like apply, common lisp has a function called funcall. Funcall works exactly like apply, except funcall expects the arguments to its function argument to appear one right after another directly after the function argument, rather than in a list. Interprete the free symbols of a function passed as an argument is sometimes called the functional argument or funarg problem. In this case, the free symbols will ordinarily be interpreted in the context that exists when the function is applied. Actually we prefer a function in which free symbols will always be interpreted in the context in which that function was created. This function ia called a closure. (will be discuss next). →→→ (setq x '(cons a '(b c))) (CONS A '(B C)) →→→ (eval x ) (A B C)

→→→ (setq a 'b) B →→→ (setq b 'c) C →→→ a B →→→ b C →→→ (eval a ) C

→→→ (defun our-if (test true false) (cond (test (eval true) (t (eval false))))

13 or →→→ (defun our-if (test true false) (eval (cond (test true) (t false)))) →→→ (setq ∗∗∗n∗∗∗ 5 ) 5

→→→ (our-if (> ∗∗∗n∗∗∗ 3) '(- ∗∗∗n∗∗∗ 3) ) '(+ ∗∗∗n∗∗∗ 3) 2 →→→ (setq ∗∗∗n∗∗∗ 1 ) 1 →→→ (our-if (> ∗∗∗n∗∗∗ 3) '(- ∗∗∗n∗∗∗ 3) ) '(+ ∗∗∗n∗∗∗ 3) 4

14. Mapping Functions.

Applicable if you want to do the same operation to several sets of arguments.

→→→ (mapcar '1+ ' (100 200 300)) (101 201 301) →→→ (mapcar '+ '(1 2 3 4) ' (100 200 300 400))) (101 202 303 404) →→→ (mapcar 'atom '(a b c (x y) nil (a b) x y)) (T T T NIL T NIL T T)

→→→ (defun paint (object color) (setf (get object 'color) color)) PAINT →→→ (paint 'wall4 'white) WHITE →→→ (get 'wall4 'color) WHITE

→→→ (mapcar 'paint ; paint is a function (table chair bed) (brown white pink)) (BROWN WHITE PINK)

→→→ (mapc 'paint ; similar w/ mapcar (table chair bed) (brown white pink)) (TABLE CHAIR BED)

→→→ (maplist 'cons '(a b) '{x y)) ;first maplist apply cons to entire arguments (((A B) X Y) ((B) Y)) ;then to the succesive cdr of list until cdr = nil

→→→ (maplist 'list '(a b) '{x y)) (((A B) (X Y) ((B) (Y))) mapl is cdr equivalent of mapc while maplist is cdr equivalent of mapcar

→→→ (apply 'append (mapcar 'find-candidates list-of-arguments)) →→→ (apply 'append '((a b c) nil (d e) nil (f g h))) 'list '(a b) '{x y)) (A B C D E F G H)

14 15. Lambda. Lambda notations are used for nameless functions. Nameless function usually a small function, which is used once and then we throw it away.

→→→ (defun red-symbol-p (a) (and (symbolp a) (equal (get a 'color) 'red))) →→→ (setf (get 'b 'color) 'red) RED →→→ (mapcar 'red-symbol-p '(a b c)) (NIL T NIL)

The function above can be replaced using lambda notation as:

→→→ (mapcar '(lambda (a) (and (symbolp a) (equal (get a 'color) 'red))) '(a b c)) (NIL T NIL)

A primitive lisp mechanism for defining functions is using symbol-function and lambda expression instead of defun.

→→→ (setf (symbol-function 'cubed) '(lambda (x) (* x x x))) (LAMBDA (X) (* X X X))) →→→ (cubed 3) 27

→→→ ((lambda (x y) (cons y x)) '(b) 'a) ;similar w/ xcons below (A B)

→→→ (defun xcons (x y) (cons y x)) XCONS →→→ (xcons '(b) 'a) (A B)

→→→ ((lambda ( ) 'hello) HELLO

(defun say-hello ( ) 'hello) SAY-HELLO →→→ (say-hello) HELLO

The Function function as we use quate (mapcar (function (lambda (a) (and (symbolp a) (equal (get a 'color) 'red)))) '(a b c)) (NIL T NIL)

→→→ (sum-loop (function sqrt) 10) 22.4682781 →→→ (sum-loop #'sqrt 10) ; same as above 22.4682781

15

→→→ (sum-loop (function (lambda (x) (* x x x ))) 15) 14400 →→→ (sum-loop (#'(lambda (x) (* x x x ))) 15) 14400

16. Reading and Writing. Read is a function in lisp with no arguments. When read function is called, lisp wait for a s- expression key-in by the user, and return the value of read. →→→ (setq x (read)) ; read w/o argument & quote then lisp wait for input (a b c) ; user input the s-expression (A B C) ; the result/value return of read →→→ x (A B C)

→→→ (prog1 ( 'enter) (setq x (read))) ;print function w one argument ;print will display on screen in ENTER (a b c) ;newline ENTER →→→ x (A B C)

Read doesn't prompt for input, it is only read from the terminal while print only the objects in the newline. Read and print only deals with s-expression.

→→→ (loop (print 'number>>> ) (let ((in (read))) (if (equal in 'end) (return nil)) (print (sqrt in)))) NUMBER>>> 16

4.0 NUMBER>>> 9

3.0 NUMBER>>> end NIL

→→→ (loop (print 'number>>> ) (let ((in (read))) (if (equal in 'end) (return nil)) (prin1 (sqrt in)))) NUMBER>>> 16 4.0 NUMBER>>> end NIL

→→→ (loop (print 'number>>> ) (let ((in (read))) (if (equal in 'end) (return nil)) (prin1 (sqrt in)) (terpri))) ;function for new line NUMBER>>> 16 4.0

16 NUMBER>>> 25 5.0

NUMBER>>> end NIL

→→→ (loop (print '(Please enter a number>>> )) (let ((in (read))) (if (equal in 'end) (return nil)) (prin1 (sqrt in)) (terpri))) (PLEASE ENTER A NUMBER>>>) 16 4.0

→→→ (loop (mapc (function print) '(Please enter a number>>> )) (let ((in (read))) (if (equal in 'end) (return nil)) (prin1 (sqrt in)) (terpri))) PLEASE ENTER A NUMBER>>> 16 4.0

Escape characters are used to print special characters in lisp such as: abcd -- will be printed by lisp ABCD a\bcd -- AbCD a\b\ -- AbcD |abcd| -- abcd

→→→ (loop (print '|Please enter a number>>> |) (let ((in (read))) (if (equal in 'end) (return nil)) (prin1 (sqrt in)) (terpri))) |PLEASE ENTER A NUMBER>>>| 16 4.0

→→→ (loop (princ '|Please enter a number>>> |) (let ((in (read))) (if (equal in 'end) (return nil)) (prin1 (sqrt in)) (terpri))) PLEASE ENTER A NUMBER>>> 16 4.0

There is no standard command in common lisp to redirect an I/O, the steps is: →→→ (setq our-own-stream (open 'our-file :direction :output) ;open output # →→→ (print '(a b c d e) our-own-stream) (A B C D E) →→→ (print 'samantha our-own-stream) SAMANTHA →→→ (close our-own-stream) NIL

→→→ (setq our-own-stream (open 'our-file :direction :input) ;open input #

17 →→→ (read our-own-stream nil 'eof) (A B C D E) → (read our-own-stream nil 'eof) SAMANTHA →→→ (close our-own-stream nil 'eof) EOF

Additional notes: 1. Function pathname can be used in most common lisp, and use pathname as an argument to open the file. 2. Function pprint works as print sintaks but for "pretty printing". 3. Function can be used to print in certain format, such as character O for printing in Octal, D for decimal, B for binary and X for hexadecimal and directives P causes a lowercase s to be printed if the argument is not 1 (plural)

→→→ (setq n 342391) 342391 →→→ (format nil "n in octal is "O" n) "n in octal is 1234567" →→→ (format nil "n in octal is "9O" n) "n in octal is 1234567" →→→ (format nil "n in octal is "9,'0O" n) "n in octal is 001234567" →→→ (format nil "n in octal is ":O" n) "n in octal is 1,234,567" →→→ (format nil ""D boy":P left" 5) "5 boys left" →→→ (format nil ""D boy":P left" 1) "1 boy left"

4. The symbol ∗∗∗read-base∗∗∗ and ∗∗∗print-base∗∗∗ will change the radix of the number.

→→→ (setq ∗∗∗read-base∗∗∗ 8) 8 →→→ 10 8 ; 10 is interpreted as an octal number

Other variables are also available such as ∗∗∗print-length∗∗∗ and ∗∗∗print-level∗∗∗

17. Debugging.

→ (1+ 8 9) Error: Debug1>: quit

Debugger commands: ? : display text for debugger commands BACKTRACE: displays a backtrace of the control stack BOTTOM : to the first stack frame CONTINUE : causes the debugger to return NIL DOWN : move to the previous stack frame ERROR : display the current error message EVALUATE : evaluate a specified form GOTO : move to a specified stack frame HELP : display help text for debugger commands QUIT : exit to a previous command level REDO : invoke the function in the current frame RETURN : return one or more specified values SEARCH : search for frame containing specified function

18 SET : modify a component of the current frame SHOW : display information about the current frame STEP : single step evaluation from current frame TOP : move to the last stack frame UP : move to the next stack frame WHERE : redisplay the current stack frame

Lisp stores on a stack the sequence of forms that it is currently evaluating. The stack is sometimes called a control stack. Each entry on the stack corresponding to a form is called a stack frame.

(cons x (foo I)) → (defun baz (y) (prog (x) (setq x 1) (foo (cons 'a y)))) baz → (baz '(b c)) Error: Attempt to take the CAR of 8, which is not a list. Debug 1> backtrace Frame #8: (CAR 8) Frame #7: (CONS (CAR 8) Y) Frame #6: (SETQ X (CONS (CAR 8) Y)) Frame #5: (PROG (X) (SETQ X (CONS (CAR 8) Y))) Frame #4: (FOO (CONS (QUOTE A) Y)) Frame #3: (PROG (X) (SETQ X 1) (FOO (CONS (QUOTE A) Y))) Frame #2: (BAZ (QUOTE (B C))) Frame #1: (EVAL (BAZ (QUOTE (B C))))

You are at Frame #8: (car 8) Debug 1>

Debug 1> backtrace 4 Frame #8: (CAR 8) Frame #7: (CONS (CAR 8) Y) Frame #6: (SETQ X (CONS (CAR 8) Y)) Frame #5: (PROG (X) (SETQ X (CONS (CAR 8) Y)))

You are at Frame #8: (car 8) Debug 1>

→ (defun xcons (x y) (cons y x) xcons → (trace xcons) → (xcons '(b c) 'a) 1 xcons ((b c) a) 1 xcons (a b c) (a b c)

→ (defun foo (x y) (xcons x y) foo → (trace foo) (foo) → (foo '(b c) 'a) 1 foo ((b c) a) |1 xcons ((b c) a) |1 xcons (a b c) 1 foo (a b c) (a b c)

19 → (defun factorial (n) (cond ((zerop n) 1) (t (* n (factorial (1 - n)))))) factorial → (factorial 4) 24 → (trace factorial) (factorial) → (factorial 4) 1 factorial (4) 2 factorial (3) 3 factorial (2) 4 factorial (1) 5 factorial (0) 5 factorial 1 4 factorial 1 3 factorial 2 2 factorial 6 1 factorial 24 24 → (untrace factorial) (factorial)

(trace (foo if expression)) ; if expression not nil, trace is called

(trace (foo in baz)) ; foo that occur within the function baz should be traced

(trace (foo break)) ; enter the debugger whenever foo is encountered.

Function step is used if we want to watch a single step of computation

→ (step (baz '(b c))) (BAZ (QUOTE (B C))) Step 1> ? ? : display help text for stepper commands BACKTRACE: displays a backtrace of the current problem DEBUG : invoke the debugger EVALUATE : evaluate a specified form FINISH : complete evaluation without the stepper HELP : display help text for the stepper command OVER : evaluate current form with stepping disabled QUIT : exits the stepper RETURN : return the specified values SHOW : display current form without abbreviation STEP : single step the current form UP : return to the containing form

Please try all these step commands by yourself.

18. Flexible Functions. We've learned that lisp has ordinary functions which treat their supplied arguments in different ways such as: ♦ + and cons evaluate all their arguments ♦ defun do not cause any argument evaluation ♦ setq only evaluate one argument ♦ cond and prog evaluate their arguments based on certain condition ♦ + tolerate any number arguments, while others expect a fixed number

20 We need to use defun and lambda expression to create function that doesn't cause its arguments to be evaluated or that accepts a variable number of arguments or keyword arguments instead of ordinary arguments also.

→ (defun power (base &optional exp) (expt base (if exp exp 2) POWER → (power 3) 9 → (power 3 4) 81

&optional means after this parameter the arguments only will be assigned if available. Sintaks : (a b c &optional x (y y-init) (z z-init zflag))

&rest is parameter used to indicate any number of parameter sintaks : (a b c …. &optional x (y yinit) …. &rest restparam)

&key is parameter used to indicate keyword parameter sintaks: (defun foo (&key switchx switchy) ….) ;switchx & switychy key par

19.Macros. Other function in lisp produce a result that is passed on as their value. Lisp macro first produce a result that is itself another peace of code. This piece of code is then evaluated to produce a value that the code return when macro is called.

→ (defmacro get-state-field (location) ;macro defined (list 'cadr location)) GET-STATE-FIELD →→→ (get-state-field '(berkeley california 94720)) ;macro evaluated CALIFORNIA → (macroexpand '( get-state-field (location)) ;see the code in macro (CADR LOCATION); T

Other examples of macro

→ (defmacro flambda (&rest I) ;macro defined (list 'function (cons 'lambda I))) FLAMBDA → (macroexpand '( flambda (x y) (cons y x))) (FUNCTION (LAMBDA (X Y) (CONS Y X))); T

→ (defmacro our-pop (stack) ;macro defined (list 'prog1 (list 'car stack) (list 'setq stack (list 'cdr stack)))) OUR-POP → (macroexpand '( our-pop stksym)) (PROG1 (CAR STKSYM) (SETQ STKSYM (CDR STKSYM))); T → (setq stack '( a b c)) (A B C) → (our-pop stack) A → stack (B C)

21

→ (defmacro our-push (e stack) ;macro defined (list 'setq stack (list 'cons e stack))) OUR-PUSH → (macroexpand '( our-push 'x stack)) (SETQ STACK (CONS X STACK )); T → stack (B C) → (our-push 'x stack) (X B C) → stack (X B C)

Defmacro allows two additional parameter designators, called &body and &whole. &body is identical with &rest in function. &whole rarely used.

→ (defmacro flambda (&rest I) ;macro defined (list 'function (cons 'lambda I)))

→ (defmacro flambda (paramlist &body I) ;macro defined (list 'function (cons 'lambda (cons paramlist I))))

→ (defmacro our-dolist (paramarg &body I) ;macro defined (append (list 'do* (list (list 'Itemp (cadr paramarg) '(cdr Itemp)) (cons (paramarg) '((car Itemp) (car Itemp)))) (list '(null Itemp) (caddr paramarg))) I))

→ (defmacro our-dolist ((var listform &optional resultform) &body I) (append (list 'do* (list (list 'Itemp listform '(cdr Itemp)) (cons var '((car Itemp) (car Itemp)))) (list '(null Itemp) resultform)) I))

22