320 likes | 484 Vues
This course, taught by Alok Mehta, explores the fundamental concepts of programming in Lisp, including the definition and use of procedures, variables, and conditionals. Key topics include procedure declaration using `defun`, understanding scope, and parameter passing in Lisp. Students will learn to write user-defined functions, compute distances between points, and effectively use local variables with `let` and `let*`. The course also covers practical exercises such as solving quadratic equations and introduces progressive enveloping techniques for building complex expressions.
E N D
66-2210-01 Programming in Lisp Procedures, Variables, Conditionals 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Procedure Declaration • Simple procedure in C/C++ to square a number • double sqr (double x) { • return x * x; • } • Equivalent function in Lisp • (defun sqr (x) (* x x)) • Note • C/C++ implementation is strongly typed; Lisp is not • Value returned by procedure is the last expression evaluated • (defun sqr (x) • (+ 2 3) • (* 7 8) • (+ x 3) • (* x x)) 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Defun • Defun is a Lisp procedure • (defun <proc-name> • (<parameter1> <parameter2> ...) • <expression1> <expression2> ...) • Side effect • defines a user-defined lisp procedure • Returns the name of the procedure defined • Defun does not evaluate its arguments • Resulting user-defined procedure is used like any other Lisp procedure • > (defun sqr (x) (* x x)) • SQR • > (sqr 5) • 25 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Scope • Consider • > (setf a ’ORIG-A b ’ORIG-B c ’ORIG-C) • ORIG-C • > (list a b c) • (ORIG-A ORIG-B ORIG-C) • > (defun myfun (a) (setf a ’myfun-a) • (setf b ’myfun-b) (list a b)) • > (myfun c) • (MYFUN-A MYFUN-B) • > (list a b c) • (ORIG-A MYFUN-B ORIG-C) • Value of C is copied to A • Parameter passing: Pass by Value (Like C/C++ default) • Global variables are still accessible! • Like C/C++ Global variables • Lexical variable: variable declared as a parameter • Special variable: variable not declared as a parameter A,B,C A 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Distance • Write a function to find the distance between 2 points. • > (defun sqr (x) (* x x)) • SQR • > (defun distance (x1 y1 x2 y2) • (sqrt (+ (sqr (- x2 x1)) (sqr (- y2 y1))))) • DISTANCE • > (setf originx 0 originy 0) • 0 • > (distance originx originy 2 2) • 1.414 • Must have correct number of arguments • The value of each argument is copied to the corresponding parameter • originx copied to x1 • originy copied to y1 • 2 copied to x2 • 2 copied to y2 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Let • Let = Lisp’s way of defining local variables • (let ( (<var1> <value1>) • (<var2> <value2>) … ) • <expr1> • <expr2> • ) • Example • (defun distance (x1 y1 x2 y2) • (let ( (dx (- x2 x1)) • (dy (- y2 y1)) ) • (sqrt (+ (sqr dx) (sqr dy))) )) • Let evaluates in parallel (not sequentially) • Uses original values of variables in all (<var> <value>) pairs • (let ( (dx (- x2 x1)) (dy (- y2 y1)) • (dx_sqr (sqr dx)) (dy_sqr (sqr dy)) ) ;; Won’t work! • (sqrt (+ dx_sqr dy_sqr)) ) 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Let vs. Let* • Let - Parallel evaluation • > (setf x ’outside) • OUTSIDE • > (let ((x ’inside) (y x)) (list x y)) • (INSIDE OUTSIDE) • Let* - Sequential evaluation • > (setf x ’outside) • OUTSIDE • > (let* ((x ’inside) (y x)) (list x y)) • (INSIDE INSIDE) • Let* Implementation of distance • (let* ( (dx (- x2 x1)) (dy (- y2 y1)) • (dx_sqr (sqr dx)) (dy_sqr (sqr dy)) ) ;; OK! • (sqrt (+ dx_sqr dy_sqr)) ) 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Exercise • 1. Rewrite the distance function to use “setf” instead of “let”. Explain the difference. • 2. Write the function solve-quadratic such that, given a,b,c, the function finds all values of x for which ax^2 + bx + c = 0. • x1 = (-b + sqrt (b^2 - 4ac)) / 2a • x2 = (-b - sqrt (b^2 - 4ac)) / 2a The function should return both values of x as a list of two elements. For example, • > (solve-quadratic 1 -2 1) • (1.0 1.0) 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Progressive Envelopment • Build up complex expressions incrementally • Technique of “Bottom-Up Design” • x1 = (-b + sqrt (b^2 - 4ac)) / 2a • > (setf a 1 b -2 c 1) • 1 • > (* b b) • 4 • > (* 4 a c) • 4 • > (- (* b b) (* 4 a c)) • 0 • > (setf sqrt_clause (sqrt (- (* b b) (* 4 a c)))) • 0 • > (setf neg_b (- b)) • 2 • > (setf two_a (* 2 a)) • 2 • > (setf x1 (/ (+ neg_b sqrt_clause) two_a)) • 1 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Progressive Envelopment (2) • Solution to solve-quadratic • (defun solve-quadratic (a b c) • (let ((sqrt_clause (sqrt (- (* b b) (* 4 a c)))) • (neg_b (- b)) • (two_a (* 2 a)) ) • (list (/ (+ neg_b sqrt_clause) two_a) • (/ (- neg_b sqrt_clause) two_a)))) • Notes - No error checking is done • (- (* b b) (* 4 a c)) might result in a negative number • What happens when you try to take sqrt of a negative number? • What happens when the value of A is zero? • Need • Predicates - to determine when error conditions occur • Conditionals - to do something else when error occurs 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Comment Translation • Break down the problem incrementally • Technique of “Top-Down Design” • x1 = (-b + sqrt (b^2 - 4ac)) / 2a • Steps to solve this: • ; Solve for x1 • ; Solve for x2 • ; Combine solutions into a list • Break down problem of solving for x1 • ; Evaluate Numerator • ; Evaluate Denominator • ; Divide Numerator / Denominator • Break down problem of solving for Numerator • ; Evaluate -b • ; Evaluate sqrt clause • Break down problem of solving for sqrt clause • ; Evaluate b^2 • ; Evaluate 4ac • ; Subtract b^2 - 4ac • ; Take the square root 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Comment Translation (2) • Continue refining solution until it is easy to solve • ; Evaluate b^2 • (* b b) • ; Evaluate 4ac • (* 4 a c) • ; Subtract b^2 - 4ac • (- (* b b) (* 4 a c)) • ; Take the square root • (sqrt (- (* b b) (* 4 a c))) 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Predicates; Equal • Predicate - Procedure that returns true or false • false is represented by NIL • true is represented by T (or, anything else) • Equal - Are two argument values the same expr? • > (equal (+ 2 2) 4) • T • > (equal (+ 2 2) 3) • NIL • > (setf l ’(this is a list)) • (THIS IS A LIST) • > (equal l (reverse ’(list a is this))) • T 66 2210 - Programming in Lisp; Instructor: Alok Mehta
EQUAL does not = EQL • Several predicates check equality • Slightly different semantics • More efficient than EQUAL • Equality predicates • Equal - Are two argument values the same expression? • Eql - Are two argument values the same symbol or number? • Eq - Are two argument values the same symbol? • = - Are two argument values the same number? 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Relationships Bet Equality Pred’s EQUAL F • EQ vs. = • = returns T if two numbers are the same, regardless of their type • EQ returns T if two arguments are the same symbol • Same chunk of memory • Identical primitives sometimes are EQ • Examples • > (eq 4 4) ;; EQ:T =:T (C) • > (eq (/ 1 4) 0.25) ;; EQ:NIL =:T (A) • > (eq ’A ’A) ;; EQ:T =:Error (D) • > (eq 4.0 4.0) ;; EQ:NIL =:T (A) = EQL A EQ D E B C 66 2210 - Programming in Lisp; Instructor: Alok Mehta
EQL vs. = • EQL • Arguments are EQL if they are either EQ or they are equivalent numbers of the same type • Examples • > (eq 4.0 4.0) ;; EQ:NIL EQL:T =:T (B) • > (eq 4 4.0) ;; EQ:NIL EQL:NIL =:T (A) • EQUAL • Arguments are EQUAL if they are either EQL or they are Lists whose elements are EQUAL • Performs an element by element comparison of lists 66 2210 - Programming in Lisp; Instructor: Alok Mehta
EQUAL vs. EQL vs. = C • EQUAL vs. EQL • > (setf X ’(A (B (C)))) • > (setf Y X) • > (setf Z ’(A (B (C)))) • X and Y are EQUAL and EQL • X and Z are EQUAL but not EQL • They don’t point to the SAME memory • But, if you do an element by element comparison of the lists, they are equal • EQUAL vs. = • > (EQUAL 4 4.0) • NIL • > (= 4 4.0) • T B A X C Y B A Z 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Equality; MEMBER • Checking for Equality • Semantics can be confusing • General Rule of Thumb • Use = when you want to compare numbers • Use EQUAL otherwise • MEMBER • Checks if first argument is an element of second argument • Returns what is left of the list when symbol is found • > (setf sentence ’(tell me more about your mother please)) • > (member ’mother sentence) • (MOTHER PLEASE) • Only checks the top level for a match (using EQL) • > (member ’mother ’((father son) (mother daughter))) • NIL 66 2210 - Programming in Lisp; Instructor: Alok Mehta
MEMBER; Keyword Modifiers • MEMBER tests for membership using EQL • > (setf pairs ’((maple shade) (apple fruit))) • > (first pairs) • (MAPLE SHADE) • > (member (first pairs) pairs) • ((MAPLE SHADE) (APPLE FRUIT)) • > (member ’(maple shade) pairs) • NIL • Use keyword modifier to override • > (member ’(maple shade) pairs :test #’equal) • ((MAPLE SHADE) (APPLE FRUIT)) • :test is a keyword; it expects an argument of type procedure • #’equal is a keyword argument • #’ is a macro • #’equal expands to (function equal) • Returns the procedure object named “equal” 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Keywords; Procedure Macro • Why use keywords? • Why not just an optional parameter? • > (member ’(maple shade) pairs #’equal) • Keywords allow more than one type of behavior modification • :test-not is another keyword for MEMBER • Why use procedure objects? • Why not just allow procedure name to be passed? • > (member ’(maple shade) pairs :test equal) • Procedure objects can be bound to variable names • > (setf predicate #’equal) • > (member ’(maple shade) pairs :test predicate) • Can pass them as parameters to functions, etc. 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Data Type Predicates • Data Type Predicates • Compare objects to determine their type • atom - Is argument an atom? • numberp - Is argument a number? • symbolp - Is argument a symbol (a non-numeric atom)? • listp - Is argument a list? • Examples • > (list pi ’ABC) • (3.14159 ABC) • > (list (atom pi) (atom ’ABC)) • (T T) • > (list (numberp pi) (numberp ’ABC)) • (T NIL) • > (list (symbolp pi) (symbolp ’ABC)) • (NIL T) • > (list (listp pi) (listp ’ABC) (listp ’(A B)) • (NIL NIL T) 66 2210 - Programming in Lisp; Instructor: Alok Mehta
NIL Revisited; NULL, ENDP • NIL is a (empty) list • > (eq nil ’()) ; T • > (eql nil ’()) ; T • > (equal nil ’()) ; T • > nil ; NIL • > () ; NIL • > (atom nil) ; T • > (symbolp nil) ; T • > (listp nil) ; T • NULL, ENDP - Return T if argument is an empty list • ENDP Causes error if argument is not a list • > (null nil) ; T • > (endp nil) ; T • > (null ’(this is not empty)) ; NIL • > (endp ’(this is not empty)) ; NIL • > (null ’ABC) ; NIL • > (endp ’ABC) ; ERROR 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Number Predicates • Number predicates • numberp - Is it a number? • zerop - Is it zero? Argument must be a number • plusp - Is it positive? Argument must be a number • minusp - Is it negative? Argument must be a number • evenp - Is it even? • oddp - Is it odd? • > - Is the list of arguments in descending order? (e.g. (> 5 4)) • < - Is the list of arguments in ascending order? • Note: Predicates often end in the letter “p” • Coffeep? Endclassp? 66 2210 - Programming in Lisp; Instructor: Alok Mehta
And, Or, Not • And, Or • Used to combine predicates • Shortcut evaluation • Stops processing as soon as the answer is known • > (and (ARG1) (ARG2) NIL (ARG3)) • ARG3 is never evaluated! • > (or (ARG1) (ARG2) T (ARG3)) • ARG3 is never evaluated! • Returns the value of the last expression evaluated • > (and 3 4 NIL 9 (+ 3 2)) ; Returns NIL • > (and 3 4 5 9 (+ 3 2)) ; Returns 5 • > (or NIL (+ 3 2) NIL 4 8) ; Returns 5 • Not • Changes NIL to T; Changes everything else to NIL 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Exercises • Define palindromep • If elements of a list read the same from left-to-right as they do from right-to-left, return true. • (palindromep ’(a b c d d c b a)) • T • (palindromep ’(a b c b a) • T • (palindromep ’(a b b c)) • NIL 66 2210 - Programming in Lisp; Instructor: Alok Mehta
If • If • Template • (if <test> <then-form> <else-form>) • Example • (defun solve-quadratic (a b c) • (let ((clause (sqrt (- (* b b) (* 4 a c)))) • (neg_b (- b)) • (two_a (* 2 a)) ) • (if (minusp clause) • NIL • (list (/ (+ neg_b (sqrt clause)) two_a) • (/ (- neg_b (sqrt clause)) two_a))))) • Either the second argument or the third argument are evaluated • Never both! • IF is a Conditional - result depends on value of <test> 66 2210 - Programming in Lisp; Instructor: Alok Mehta
If, When, Unless • If • (if <test> <then-form> <else-form>) • if <test> is true • <then-form> is evaluated, • otherwise <else-form> is evaluated. • When • (when <test> <then-form1> <then-form2> …) • If <test> is true, then other arguments are evaluated. • Unless • (unless <test> <else-form1> <else-form2> …) • If <test> is false, then other arguments are evaluated. 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Exercises • Write function to find the maximum of two numbers • Write function to take the absolute value of two numbers. 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Cond • Cond format • (COND (<test1> <then-1-1> <then-1-2> …) • (<test2> <then-2-1> <then-2-2> …) • (<test3> <then-3-1> <then-3-2> …) • … • (<testi> <then-i-1> <then-i-2> …) • … • (<testm> <then-m-1> <then-m-2> …) • Semantics • 1. Evaluate <test1>, <test2>, … until you get to a <testi> such that <testi> evaluates to a nonNIL value • 2. Evaluate <then-i-1> <then-i-2> … • 3. Return value of the last <then-i-n> clause executed • If all tests evaluate to NIL, result of COND is NIL 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Example • Define a function to find area • (defun area (type r) • (cond ((eq type ’circle) (* PI R R)) • ((eq type ’sphere) (* 4 PI R R)) • ((eq type ’square) (* R R) • ((eq type ’cube) (* 6 R R)) • ( t (print “Error”) )) • Define a function, compute-grade, to determine the letter grade. • (compute-grade 81.5) • B 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Case • Similar to COND, but is more elegant when checking for equality • (defun area (type r) • (case type • (circle (* PI R R)) • (sphere (* 4 PI R R)) • (square (* R R) • (cube (* 6 R R)) • (otherwise (print “Error”) )) • Format • (case <key-form> • (<key 1> <then-1-1> <then-1-2> …) • (<key 2> <then-2-1> <then-2-2> …) • … • (<key m> <then-m-1> <then-m-2> …) • (otherwise <then-o-1> <then-o-2> …) 66 2210 - Programming in Lisp; Instructor: Alok Mehta
Case (2) • Notes • <key-form> is evaluated • But, <key 1> <key 2>, … are NOT evaluated • “OTHERWISE” or “T” always evaluate to nonNIL • If no matches are found, the CASE statement returns NIL • A <key> form may contain a list. In this case, the MEMBER function is used to do the comparison. • (defun circularp (type) • (case type • ((circle sphere) ’T) • (otherwise NIL))) • (circularp ’cube) 66 2210 - Programming in Lisp; Instructor: Alok Mehta