* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Function Design
Survey
Document related concepts
Transcript
Function Design in LISP Program Files LISP programs are plain text – DOS extensions vary; use .lsp for this course (load “filename.lsp”) Can use Unix-style paths – (load “c:/Work/Comp2043/A4/myFile.lsp”) – (load “A4/myFile.lsp”) – (load “A4\\myFile.lsp”) OK in Windows Comments For this course: – identify file as we did with Prolog programs – function comments similar to predicates – also say what gets returned ;; (fib N) ;; -- returns the Nth Fibonacci number, N > 0 ;; -- no error checking (infinite loop if N =< 0) Comments Many similar functions – conversion functions, for example One comment for all ;; (print-no-X-warning N) ;; -- where X in {student, course, section} ;; -- print a warning message that there is no ;; object X corresponding to N ;; -- N is a student number, course number, etc. Functional Cohesion You should be able to describe what your function does in a simple sentence – how it’s doing it may require more explanation If you need the word “and”, you’re probably doing too much! – see if you can split it into two functions… – …or move some functionality into another fn Non-Cohesive Function ;; (squeeze-input) ;; -- rewrite output getting rid of excess spaces … ;; (punc L) ;; -- checks whether L is punctuation ;; and if it isn’t it prints a space ;; and continues “squeezing” input Cohesive Function ;; (squeeze-input) ;; -- rewrite output getting rid of excess spaces … ;; (punc L) ;; -- says whether L is a punctuation character Let (squeeze-input) worry about printing spaces and continuing squeezing input Writing Functions in LISP First (as usual): understand what’s required – what are you given? – what is the value to return? Second: plan how to get result – break down into its conditions (if any) – identify easy cases – break harder cases down into parts Functions and Lists List argument generally needs to be broken into parts – (first L) – operate on this directly – (rest L) – recur on this Mapped parts need to be re-combined – maybe some math function – atomic result – usually using CONS – list result Implementing a Plan Plan is in steps: – calculate this – use it to calculate that All must be combined into one function call Early calculations become arguments for later ones – will evaluate from the inside out Plus-1 List: Imperative Add one to each element of a list plus1List(L) if (L == nil) variables not necessary return nil; else var newFirst first(L) + 1; var newRest plus1List(rest(L)); return cons(newFirst, newRest); Plus-1 List: Imperative Add one to each element of a list plus1List(L) if (L == nil) replace conditional command return nil; with conditional expression else return cons(first(L) + 1, plus1List(rest(L))); Plus-1 List: Imperative Add one to each element of a list plus1List(L) return (L == nil) ? nil now functional: rewrite to LISP : cons(first(L) + 1, plus1List(rest(L))); Plus-1 List: LISP Add one to each element of a list (defun plus1List (L) (if (null L) nil make more “idiomatic” (cons (+ (first L) 1) (plus1List (rest L))))) Plus-1 List: LISP Add one to each element of a list (defun plus1List L (unless (null L) (cons (+ (first L) 1) (plus1List (rest L))))) (unless (null Arg) (cons (…(first Arg)…) (…(rest Arg)…))) programming idiom translating a list Functional Abstraction Complicated (or repeated) steps should get their own function definitions – apply same process again – understand what you want out of the function (don’t let the code control you) Laziness is a virtue – leave it for later – but make sure you understand it, first Example Standard deviation (population) – square root of the average of the deviations – given a list of numbers, returns a number Functional abstraction – square root is built in, average we can build – deviations??? Time to be lazy! (defun stdevp (L) (sqrt (average (deviations L)))) Sub-Problems Average – given a list of numbers, return a number – add up the numbers, divide by the # of numbers – left as an exercise Deviations – deviation = difference from average, squared – given a list of #s, return another list of #s Deviations Need the average of the list – use the average function: (average L) Need to find the deviation for every element in the list – its difference from the average – time to be lazy again – another function – given a list & its average, return list of deviations – (deviation-list L (average L)) Deviation List Need to process a list & return a list – break down list (using first & rest) – calculate deviation (separate function on first, recursion on rest) – reconstruct list (using cons) Unless the list is empty, of course (unless (null L) (cons (…(first L)…) (…(rest L)…))) Calculation of deviation of first Calculation of deviations of rest Calculating a Single Deviation Given a number and the mean, return a number (its deviation) – their difference, squared – use expt for squaring (expt x 2) = x2 (defun calculate-deviation (Value Mean) (expt (– Value Mean) 2)) List of Deviations (defun deviation-list (L M) (unless (null L) (cons (calculate-deviation (first L) M) (deviation-list (rest L) M) ) ) ) (defun deviations (L) (deviation-list L (average L))) Function Call Calculate standard deviation (population) of the list (5 10 15) > (stdevp ‘(5 10 15)) (sqrt (average (deviations ‘(5 10 15)))) (average (deviations ‘(5 10 15))) (deviations ‘(5 10 15)) (deviation-list ‘(5 10 15) (average ‘(5 10 15))) = (deviation-list ‘(5 10 15) 10) Function Call (cont.) (deviation-list ‘(5 10 15) 10) (unless (null ‘(5 10 15)) (…)) = (unless NIL (cons (…) (…))) (cons (calculate-deviation …) (…)) (calculate-deviation (first ‘(5 10 15)) 10) = (calculate-deviation 5 10) (expt (– 10 5) 2) = 25 = (cons 25 (deviation-list (rest ‘(5 10 15)) 10)) Function Call (cont.) (deviation-list ‘(10 15) 10) (unless (null ‘(10 15)) (…)) = (unless NIL (cons (…) (…))) (cons (calculate-deviation …) (…)) (calculate-deviation (first ‘(10 15)) 10) = (calculate-deviation 10 10) (expt (– 10 10) 2) = 0 = (cons 0 (deviation-list (rest ‘(10 15)) 10)) Function Call (cont.) (deviation-list ‘(15) 10) (unless (null ‘(15)) (…)) = (unless NIL (cons (…) (…))) (cons (calculate-deviation …) (…)) (calculate-deviation (first ‘(15)) 10) = (calculate-deviation 15 10) (expt (– 10 15) 2) = 25 = (cons 25 (deviation-list (rest ‘(15)) 10)) Function Call (cont.) (deviation-list ‘() 10) (unless (null ‘()) (…)) = (unless T (cons (…) (…))) = NIL = (cons 25 NIL) = (25) = (cons 0 ‘(25)) = (0 25) = (cons 25 ‘(0 25)) = (25 0 25) = (average ‘(25 0 25)) = 16.6667 = (sqrt 16.6667) = 4.0825 Tweaking the Code Deviations just calls deviation-list with own argument plus another Could be combined into one function – make the mean an optional argument – default value – average of the given list (defun deviations (L &optional (M (average L))) …) Will call average if & only if no mean given Combined Deviations Code (defun deviations (L &optional (M (average L))) (unless (null L) (cons (calculate-deviation (first L) M) (deviations (rest L) M) ) ) ) Note: important to pass M in recursive call – else calculates average of (10 15) = wrong Optional Parameters Use &optional in parameter list – everything before &optional is required – if not given use NIL – or default value (next) > (defun opt-args (a &optional b c) (list a b c)) OPT-ARGS > (list (opt-args 1) (opt-args 2 3) (opt-args 4 5 6)) ((1 NIL NIL) (2 3 NIL) (4 5 6)) Default Values For optional arguments – list with parameter name & default value – default calculated at call time > (defun def-args (a &optional (b 5)) (list a b)) DEF-ARGS > (list (def-args 1) (def-args 2 3)) ((1 5) (2 3)) Correlation Write a function to calculate the correlation between two lists – the two lists must be the same length Understanding – given two lists (same length) – returns a number – formula to follow Calculating a Correlation Complicated formula requires: – – – – length of lists (N) sums of lists (Sx and Sy) dot product of the two lists (Sxy) sums of squares of lists (Sxx and Syy) Result is (N*Sxy – Sx*Sy) sqrt((N*Sxx) – (Sx)2)*(N*Syy – (Sy)2)) What Do We Need? Functions that calculate: – – – – length of a list sum of a list dot product of two lists sum of squares of list Assume We Have Them Write the result calculation function (N*Sxy – Sx*Sy) sqrt((N*Sxx) – (Sx)2)*(N*Syy – (Sy)2)) Write the main function – – – – N = length of lists (must be same for both) Sx = sum of list 1st list, Sy = sum of second Sxy = dot product of lists Sxx = sums of squares of 1st list, Syy = ditto 2nd Now for the Helpers Already have the length function built in Write the sum of a list function Write the dot product function – (1 2 3) * (4 5 6) = (1*4)+(2*5)+(3*6) = 32 Write the sum of squares function – note: can use dot product function Final Result (defun correlation (Xs Ys) …) (defun correlation-calc (N Sx Sy Sxy Sxx Sxy) …) (defun sum-of-list (L) …) (defun dot-product (Xs Ys) …) (defun sum-of-squares (L) …) > (correlation ‘(5 10 15) ‘(3 6 12)) 0.989 Exercise Write a function that calculates the correlation of a list of pairs – (correlate-pairs ‘((5 3) (10 6) (15 12))) => 0.989 – list of (X Y) pairs Use the correlation function from last time – (correlation ‘(5 10 15) ‘(3 6 12)) => 0.989 – only difference is the form of the data – (write it in two lines! (hint: be lazy)) Exercise Use the list translation programming idiom we discussed earlier to write the rest of the support functions for our new correlations function – translate list of XY pairs into a list of Xs – translate list of XY pairs into a list of Ys Next Time Control over lists – Chapter 6