<<

CS 380 ARTIFICIAL INTELLIGENCE

INTRODUCTION TO LISP Santiago Ontañón [email protected] LISP introduction LISP introduction

LISP 1958 LISP introduction

SHRDLU: https://www.youtube.com/watch?v=bo4RvYJYOzI

(Reading about SHRDLU as a kid made me want to study AI!) LISP introduction

Functional language: • Avoids changing state: i.e., variables have one value, and one value only (you don’ change value of variables once you assign them). • In reality, you can (Lisp is not purely functional). But this should be avoided. • Expressionsvs Statements: in functional programming, the return value of a function should depend ONLY on the value of its parameters. Unlike in imperative languages, where there can be global state. • Recursionvs Iteration: looping is implemented using recursion, instead of iteration. LISP introduction

Invented in 1958 by John McCarthy (same guy who coined the term “Artificial Intelligence”)

What does “LISP” stand for?? LISt Processing

Simple representation and manipulation of lists ‘(A E I O U) LISP introduction

What does “LISP” stand for?? LISt Processing

Simple representation and manipulation of lists (let ((vowels ‘(A E I O U))))

NIL

A E I O U LISP on tux.cs.drexel.edu

Common Lisp is installed on tux.cs.drexel.edu clisp To quit (quit) or (exit) You can load files from the current directory (load “filename”) MIT/GNU Scheme is installed on tux.cs.drexel.edu mit-scheme To quit (quit) or (exit) You can load files from the current directory (load “filename”) LISP introduction

Primitive elements: atoms and lists • atoms: peanut butter jelly “a string” 58 • lists: ( atoms and/or lists )

(peanut butter jelly)

(peanut butter (marshmallow jelly))

NIL

peanut butter NIL

marshmallow jelly Math

All function calls in LISP follow the pattern (function_name arg1 arg2 arg3 ...)

Imperative language: f(x) LISP: (f x) means apply function f to argument x

> (+ 2 3) 5 > (- 5 7) -2 > (* 6 7) 42 Lists

In a list, first element is expected to be a function which uses remaining elements as arguments.

If the list is “data” instead of a “function call” suppress evaluation with ‘ (quote)

Let’s say we want to create a static list with numbers 1 to 5: > (print (1 2 3 4 5)) ??? Lists

In a list, first element is expected to be a function which uses remaining elements as arguments.

If the list is “data” instead of a “function call” suppress evaluation with ‘ (quote)

Let’s say we want to create a static list with numbers 1 to 5: > (print (1 2 3 4 5)) Error since 1 is not a function!!!

> (print ‘(1 2 3 4 5)) Lists

In a list, first element is expected to be a function which uses remaining elements as arguments.

If the list is “data” instead of a “function call” suppress evaluation with ‘ (quote)

Another way is using the function “list”, which creates a list with all of its remaining arguments, e.g.: (list 1 2 3) Lists

In a list, first element is expected to be a function which uses remaining elements as arguments.

If the list is “data” instead of a “function call” suppress evaluation with ‘ (quote)

Another way is using the function “list”, which creates a list with all of its remaining arguments, e.g.: (list 1 2 3)

So, what if we want to create a list with 3 numbers like this?: (print ‘(1 2 (+ 10 20))) Lists

In a list, first element is expected to be a function which uses remaining elements as arguments.

If the list is “data” instead of a “function call” suppress evaluation with ‘ (quote)

Another way is using the function “list”, which creates a list with all of its remaining arguments, e.g.: (list 1 2 3)

So, what if we want to create a list with 3 numbers like this?: (print ‘(1 2 (+ 10 20))) Doesn’t work as expected since the quote prevents evaluation! (print (list (1 2 (+ 10 20)))) Lists (extract information)

Get the first element (head) (car '(5 6 7 8)) Get the rest of the list (tail) (cdr '(5 6 7 8))

vowels: NIL

A E I O U > (car vowels) > (car (cdr vowels)) A E > (cdr vowels) > (cadr vowels) (E I O U) E Lists (extract information)

Get the first element (head) “car ” and “cdr” are for “hardcore” lisp purists. I (car '(5 6 7 8)) have always used “first” and “rest”, which are more intuitive to me. Get the rest of the list (tail) (cdr '(5 6 7 8))

vowels: NIL

A E I O U > (car vowels) > (car (cdr vowels)) A E > (cdr vowels) > (cadr vowels) (E I O U) E Lists (concatenation) CONS

Given a list L and an item x (either an atom or a list) (cons x L) returns a new list with x as first element and L as rest (L is unaffected) (let* ((L '(peanut butter jelly)) (J (cons ‘apple L))) (print J) ) > (apple peanut butter jelly)

L NIL

peanut butter jelly J It does not create a new copy of a apple list argument Code = Data

Lisp does not distinguish “code” from “data”. For example:

(let ((a ‘(+ 3 4)) (print a) ; using the content of a as data (eval a) ; using the content of a as code )

You can easily write code that: • writes/modifies itself • pass functions (or even partially defined functions) as parameters • etc. About equality eq: compares two atoms, or whether two pointers point to the same location. equal: compares whether two structures have identical form and values. (setf x '(a (b ) 1 2 3)) (setf y (car (cdr x))) (setf z (cdr x)) (setf w (car z)) (eq y w) ‘returns T (eq y ‘(b c)) ‘returns NIL (equal y ‘(b c)) ‘returns T

I am using “setf” (assignment) in this slide, for simplicity, in real Lisp program, you should minimize the use of “setf”, and use “let ” instead. About equality

(setf x '(a (b c) 1 2 3)) (setf y (car (cdr x))) (setf z (cdr x)) (setf w (car z)) (eq y w) ‘returns T (eq y ‘(b c)) ‘returns NIL (equal y ‘(b c)) ‘returns T z

x NIL

a 1 2 3 y w NIL b c NIL

b c Additional functions

Function does not need to be given a name. ( (lambda (x) (+ x x)) 7)

Define local variables for use in an expression (let ((a 4) (b 7)) (+ a b))

Apply a function to every element in a list. (defun square (x) (* x x)) => SQUARE (mapcar 'square '(1 2 3 4 5)) => (1 4 9 16 25) Conditional expressions

The if statement takes three inputs. If the first argument is true is returns the second otherwise is returns the third. (if (< 1 3) 4 5)

The cond extends the if statement to an unlimited number of cases. (cond ((< 4 5) 5) ((> 4 7) 10) (T 11) ) CASE (conditional)

CASE is like C’s “switch” The vij args aren’t evaluated otherwise is optional and is like C’s default

(case x ((v11 v12 . . .) expr11 expr12 ...) ((v21 v22 . . .) expr21 expr22 ...) ... (otherwise expr1 expr2 ...))

(setf day 4) (case day (1 (format t "~% Monday")) (2 (format t "~% Tuesday")) … (7 (format t "~% Sunday"))) Define functions

The defun command can be used for defining functions. (defun name (arg list) expression)

No loops (not true). Everything as recursive function. Example:. (defun fib (n) (if (< n 3) 1 (+ (fib (- n 1)) (fib (- n 2)))))

Once a function is defined we can apply it to arguments. (fIB 6) <- not case sensitive!!! Recursion review

Define LAST function (defun () )

(cond ( ) ( ) ... (T ))

(NULL x) True iff x is NIL Recursion review

Define (LAST L) function (defun LAST (L) (cond ((NULL L) NIL) ((NULL (cdr L)) L) (T (LAST (cdr L)))))

Define (MEMBER X L) function (use EQUAL) Recursion review

Define (LAST L) function (defun LAST (L) (cond ((NULL L) NIL) ((NULL (cdr L)) L) (T (LAST (cdr L)))))

Define (MEMBER X L) function (use EQUAL) (member 2 '(1 2 3)) => (2 3) (defun MEMBER (X L) (cond ((NULL L) NIL) ((EQUAL X (car L)) L) (T (MEMBER X (cdr L))))) Numeric functions

+, *, / plus, times, divide (/ (* 2 3 4) (+ 3 1)) ⇒ 6 - minus (- (- 3) 2) ⇒ –5 sqrt square root (sqrt 9) ⇒ 3 exp, expt exponentiation (exp 2) ⇒ e2 (expt 3 4) ⇒ 81 log logarithm (log x) ⇒ ln x (log x b) ⇒ logb x min, max minimum, maximum (min -1 2 -3 4 -5 6) ⇒ –5 abs, round absolute val, round (abs (round -2.4)) ⇒ 2 truncate integer part (truncate 3.2) ⇒ 3 mod remainder (mod 5.6 5) ⇒ 0.6 sin, cos, tan trig funcs (radians) (sin (/ pi 2) ⇒ 1.0 List functions

nth nth element, (nth 2 '(a b c d)) ⇒ c n starts at 0 length #of elements (length '((a b) c (d e))) ⇒ 3 cons concatenation (cons 'a '(b c d)) ⇒ (a b c d) (cons '(a b) 'c) ⇒ ((a b) . c) list make a list (list (+ 2 3) '(b c) 'd 'e) ⇒ (5 (b c) d e) append append lists (append '(a) '(b c) '(d)) ⇒ (a b c d) (append '(a) '(b c) 'd) ⇒ (a b c . d) reverse reverse a list (reverse '((a b) c d)) ⇒ (d c (a b)) Predicates

numberp, integerp, Test whether arg is a (numberp 5.78) ⇒ T stringp, characterp, number, integer, string, (integerp 5.78) ⇒ NIL evenp, oddp character, etc. (characterp #\a) ⇒ T listp, atom, null, Test whether arg is a (listp nil) ⇒ T consp list, atom (consp nil) ⇒ NIL empy/noempty list <, <=, =, >=, > numeric comparisons arg must be a number string<, string<=, ... string comparisons args must be string or char eq, equal equality tests (setf x '(a)) (eq x x) ⇒ T (eq x '(a)) ⇒ NIL (equal x '(a)) ⇒ T and, or, not logical predicates; not (not (evenp 8)) ⇒ NIL and null are identical (and 3 'foo T) ⇒ T Sequential execution

(progn e1 e2 ... en) evaluates e1, e2, ... , en, and returns the value of en (prog1 e1 e2 ... en) evaluates e1, e2, ... , en, and returns the value of e1 let* assigns initial values sequentially (let* ((x1 v1) (x2 v2) (x3 v3)) e1 e2 ... en)

(let ((x1 v1)) (let ((x2 v2)) (let ((x3 v3)) e1 e2 ... en))) Formatted output

(format ) is like printf in C

> (setf x "foo") > (format t "~a is ~a~%" 'x x)

X is foo NIL destination is where to send the output t ⇒ send to standard output, then return NIL control-string is like a printf control string in C ~% is a newline like \n in C ~a matches any Lisp expression Loops

(dotimes (i num [value]) expressions) executes expressions with i = 0, . . . , num − 1, then returns value or NIL (dolist (x list [value]) expressions) executes expressions with x = each element of list, then returns value or NIL (return value) returns value from the middle of a loop

(setq result nil) (dotimes (foo 5 (reverse result)) (push foo result)) ⇒ (0 1 2 3 4)

(setq result nil) (dolist (foo '(a 1 b 2 "stop here" 3 z 33)) (if (stringp foo) (return result)) (push foo result)) ⇒ (2 B 1 A) Loops

(do ((i1 start1 incr1) . . . (in startn incrn)) (termination-test [expressions to evaluate at termination]) expression1 . . . expressionn) Somewhat like C’s “for”, but the iteration variables are local, and are set simultaneously. To set them sequentially, replace do with do* Unfortunately, the syntax is a bit painful

(setf c 0) (do ((a 1 (+ a 1)) ; a = 1, 2, 3, ... (b '(1 10 3 2) (cdr b))) ; take successive cdrs ((null b) c) ; if b is empty, return c (setf c (+ c (expt (car b) a)))) ; add x^a to c

⇒ compute 11 + 102 + 33 + 24 = 144 Loops

(loop [loop clauses]) iteration macro with a huge number of options

Be careful! complex cases can be hard to understand (see ANSI , pp. 239-244)

But simple cases are easier to understand than do is:

(setf c 0) (loop for a from 1 by 1 (do ((a 1 (+ a 1)) for b in '(1 10 3 2) (b '(1 10 3 2) (cdr b))) sum (expt b a)) ((null b) c) (setf c (+ c (expt (car b) a))))

⇒ compute 11 + 102 + 33 + 24 = 144 Lisp

• Functional mixed with lots of imperative functionality.

• Data = code

• Very convenient to manipulate symbols, lists, etc.

• Syntax was defined in the 50s, where power was limited. So, it is “computer friendly”, but not very “human friendly” unless we pay close attention to our programming style. • Lisp lets us write very nasty looking programs if not being careful!!!

• Used in most early AI