Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Variable Declarations • Global and special variables – (defvar …) – (defparameter …) – (defconstant …) – (setq var2 (list 4 5)) – (setf …) • Local variables – (let ((x 10)) …) – (let* ((x 99) …) 1 Global Variables • Declared using defvar and defparameter: – (defvar <var name> <init value> <documentation>) >(defvar number-list nil "A list of numbers") • Assigned values using setf special form: – (setf <place> <new value>) >(setf x 3) 3 >x 3 • Imperative Paradigm Alert (why?) 2 Global Variables, cont. Global variables are visible throughout the program. Global variables can be created by giving a symbol and a value to defparameter or defvar. > (defparameter *foo* 1) *FOO* > *foo* Note: (defparameter v e) creates a global variable named v and sets its value to be e. 1 > (defvar *bar* (+ *foo* 1)) *BAR* > *bar* 2 > (defvar *bar* 33) *BAR* > *bar* 2 (defvar v e) is just like defparameter if no global variable named v exists. Otherwise it does nothing. 3 Global Constants and Variables • Define a global constant with defconstant > (defconstant +limit+ 100) +LIMIT+ > (setf +limit+ 99) Error: can't assign a global constant • readability conventions – +symbolname+ identifies symbols as constants – *symbolname* identifies global variables 4 Assignment Statements • Assignment operators: set, setq and setf • The most general is setf • It assigns both local and global variables: > (setf *blob* 89) 89 > (let ((n 10)) (setf n 2) n) 2 • Initialized n to 10, then executed all the statements within the scope of let 5 setf • Create global variables implicitly by assigning values > (setf x (list 'a 'b 'c)) (A B C) • However, it is better lisp style to use defparameter to declare global variables • You can give setf any even number of arguments (setf a 1 b 2 c 3) is the same as: (setf a 1) (setf b 2) (setf c 3) 6 setf cont. • You can do more than just assigning values to variables! • The first argument to setf can be an expression as well as a variable name. • In such cases, the value of the second argument is inserted in the place referred to by the first: > x (A B C) > (setf (car x) 'n) N > x (N B C) 7 setf Examples > (setq a (make-array 3)) #(NIL NIL NIL) > (aref a 1) NIL > (setf (aref a 1) 3) 3 > a #(NIL 3 NIL) > (aref a 1) 3 > (defstruct foo bar) FOO > (setq a (make-foo)) #s(FOO :BAR NIL) > (foo-bar a) NIL > (setf (foo-bar a) 3) 3 >a #s(FOO :BAR 3) > (foo-bar a) 3 8 Return or Change? • The function remove takes an object and a list and returns a new list where all occurrences of the object were removed > (setf lst '(b u t t e r)) (B U T T E R) > (remove 'e lst) (B U T T R) • Note: remove does not remove any items from the list! The original list is untouched after the call to remove: > lst (B U T T E R) • To remove the items from a list you would have to use setf: > (setf lst (remove 'e lst)) (B U T T R) • Functional programming means, essentially, avoiding setf, and other assignments. 9 I/O Input • (read [<stream>] ...) – reads the printed representation of an object from a stream • (read-char [<stream>] ...) – returns one character and advances the stream pointer • (read-char-no-hang [<stream>] ...) – returns one character if one is available (if so, advances the stream pointer) • (read-line [<stream>] ...) – read characters terminated by a newline, returns a string containing the characters • (yes-or-no-p [format-string <args>*]) – ask the user a yes/no question (yes-or-no-p "set x to 3?") 10 I/O Output • • • print - prints and returns object in lisp format > (print (list "foo" "bar")) ("foo" "bar") ("foo" "bar") princ - prints for readability, without control characters e.g. " ", returns object lisp format > (princ "hello") hello "hello" format - the most general output function (format <stream> <control-string> <arg>*) – stream t prints to *standard-output* – returns NIL – the second argument is a string template, – the remaining arguments are objects to be inserted into the template: > (format t "~A plus ~A equals ~A." 2 3 (+ 2 3)) 2 plus 3 equals 5. NIL 11 Developing Recursive Functions • Recursive function calls a copy of itself 1. Do error checking first (if needed) 2. Check for base cases (non-recursive cases) 3. Recursion • must be on a smaller problem • If number – closer to base case • If list – shorter or less complex • Avoid infinite loops!!!! • out of stack space error 12 Exercise - Write a filtering function • A function to filter out negative numbers from a list of numbers. • Examples: > (filter-negatives '(1 -1 2 -2 3 -4)) (1 2 3) > (filter-negatives '("string")) List must contain only numbers > (filter-negatives '(-1 -2 -2 -3 -4)) NIL > (filter-negatives '(9 10)) (9 10) 13 Filter-negatives 1. Error checking • Is argument a list? • Continue • End with error message 2. Test for base case(s) • Is the list empty? • Return the empty list () 3. Test the first item • Is it a number? • If not – error message • Is it a negative number? • Ignore it - recurse on the rest of the list and return that result • Is it a positive number? • Add that number to the result of recursion on the rest of the list 14 Start the function (defun filter-negatives (inlist) "takes one argument, a list of numbers and returns a list containing all the non-negative numbers in the input" (cond ; make decisions ; error – not a list? ; base case – empty list? ; what are the more complex cases? ; check first item in list -; not a number? Error or ignore ; negative number? ; Ignore, process remaining items ; positive number? ; Add to result, process remaining items ) ) 15 filter-negatives (defun filter-negatives (inlist) "takes one argument, a list of numbers and returns a list containing all the nonnegative numbers in the input" (cond ; make decisions ((not (listp inlist); not a list? (princ "Argument must be a list" ) (terpri) ; print return after string (list)) ; return an empty list 16 filter-negatives (defun filter-negatives (inlist) (cond ; make decisions ((not (listp inlist); not a list? (princ "Argument must be a list" ) (terpri) ; print return after string (list)) ; return an empty list ; base case – empty list? ((null inlist) (list)) ; return an empty list 17 Recursive Cases – Not a Number ; what are the more complex cases? ; check first item in list ; not a number? Error or ignore 18 Recursive cases – Negative Number ; negative number? ; Ignore, process remaining items 19 Recursive Cases – Positive Number ; positive number? ; add to result, process remaining items 20 filter-negatives ;;; Error checking on input - list of numbers ;;; The base case, the list is empty so return nil ;;; if first item in arg is positive, add it to the result of recursion ;;; if it is negative, throw it away, return = result of recursion (defun filter-negatives (inlist) (cond ((not (listp inlist)) ; 1st test (princ "Argument must be a list") ; print message (terpri) (list)) ; return empty list, quit ((null inlist) (list)) ; 2nd test - out of items ((not (numberp (car inlist))) ; 3rd test - not a number (princ "List must contain only numbers") ; print message (terpri) (list)) ; return empty list, quit ((>= (car inlist) 0) ; 4th test - positive number (cons (car inlist) ; add 1st to result of (filter-negatives (cdr inlist)))) ; recursion on rest ((< (car inlist) 0) ; 5th test - negative number (filter-negatives (cdr inlist)) ; ignore 1st, return value ) ) ) ; = recursion on rest ; Note: the last test could have been t (true) 21 filter-negatives • filter.lisp • www2.hawaii.edu/~janst/313/lisp/filter.lisp 22 &optional in parameter list • Gives a name to additional variable(s) in a parameter list. (defun func (arg1 &optional arg2)…) • No error if variable(s) are present or not (func 10) (func 10 20) • Default value can be specified (defun func (arg1 &optional (arg2 init2))…) (func 10) = (func 10 init2) 23 &key in parameter list • Several optional parameters, • Keywords rather than order is used to match formal names to actual names > (defun func (width &key ((:height h)) ((:depth d))) (format t "w = ~d, h = ~d, d = ~d" width h d)) FUNC > (func 1 :height 2 :depth 3) w = 1, h = 2, d = 3 NIL > (func 1 :depth 3 :height 2) w = 1, h = 2, d = 3 NIL 24 &rest in parameter list • Allows to accept any of number of parameters • Such parameters form a list > (defun list2 (&rest x) x) LIST2 > (list2 1 2 3 4 5) (1 2 3 4 5) 25 Exercise: count-occurrences • Write a function that takes two parameters • The first is an item to look for • The second parameter is a list • Returns the number of times item is found • Example: > (count-occurrences 'a '(a (a c d a) (c b a))) 1 • www2.hawaii.edu/~janst/313/lisp/count-occurrences.lisp 26 count_all_items • Now write a function that takes the same two parameters • The first is an item to look for • The second parameter is a list • The function returns the number of times the item occurs in the list at any level ofnesting • Example: >(count_all_items 'a '(b (a c d a) (c a b))) should return 3 27 Exercise: make-change • Write a function that calculates change (in US currency) > (make-change 123) ((1 DOLLARS) (2 DIMES) (3 PENNIES)) (defconstant *us-currency* '((100 dollars) (50 half-dollars) (25 quarters) (10 dimes) (5 nickels) (1 pennies))) 28 make-change (defun make-change (number) ( ; error checking ; base case(s) ; recursive case(s) • www2.hawaii.edu/~janst/313/lisp/makechange.lisp 29