function design in lisp. program files n lisp programs are plain text –dos extensions vary;...
TRANSCRIPT
Function Design in LISPFunction Design in LISP
Program FilesProgram Files
LISP programs are plain textLISP programs are plain text– DOS extensions vary; use .lsp for this courseDOS extensions vary; use .lsp for this course
(load “filename.lsp”)(load “filename.lsp”) Can use Unix-style pathsCan use Unix-style paths
– (load “c:/Work/Comp2043/A4/myFile.lsp”)(load “c:/Work/Comp2043/A4/myFile.lsp”)– (load “A4/myFile.lsp”)(load “A4/myFile.lsp”)– (load “A4\\myFile.lsp”) OK in Windows(load “A4\\myFile.lsp”) OK in Windows
CommentsComments
For this course:For this course:– identify file as we did with Prolog programsidentify file as we did with Prolog programs– function comments similar to predicatesfunction comments similar to predicates– also say what gets returnedalso say what gets returned;; (fib N);; (fib N);; -- returns the Nth Fibonacci number, N > 0;; -- returns the Nth Fibonacci number, N > 0;; -- no error checking (infinite loop if N =< 0);; -- no error checking (infinite loop if N =< 0)
CommentsComments
Many similar functionsMany similar functions– conversion functions, for exampleconversion functions, for example
One comment for allOne comment for all;; (print-no-X-warning N);; (print-no-X-warning N);; -- where X in {student, course, section};; -- where X in {student, course, section};; -- print a warning message that there is no ;; -- print a warning message that there is no ;; object X corresponding to N;; object X corresponding to N;; -- N is a student number, course number, etc.;; -- N is a student number, course number, etc.
Functional CohesionFunctional Cohesion
You should be able to describe You should be able to describe whatwhat your your function does in a simple sentencefunction does in a simple sentence– howhow it’s doing it may require more explanation it’s doing it may require more explanation
If you need the word “and”, you’re If you need the word “and”, you’re probably doing too much!probably doing too much!– see if you can split it into two functions…see if you can split it into two functions…– ……or move some functionality into another for move some functionality into another fnn
Non-Cohesive FunctionNon-Cohesive Function
;; (squeeze-input);; (squeeze-input);; -- rewrite output getting rid of excess spaces;; -- rewrite output getting rid of excess spaces……;; (punc L);; (punc L);; -- checks whether L is punctuation;; -- checks whether L is punctuation;; and if it isn’t it prints a space;; and if it isn’t it prints a space;; and continues “squeezing” input;; and continues “squeezing” input
Cohesive FunctionCohesive Function
;; (squeeze-input);; (squeeze-input);; -- rewrite output getting rid of excess spaces;; -- rewrite output getting rid of excess spaces……;; (punc L);; (punc L);; -- says whether L is a punctuation character;; -- says whether L is a punctuation character Let (squeeze-input) worry about printing Let (squeeze-input) worry about printing
spaces and continuing squeezing inputspaces and continuing squeezing input
Writing Functions in LISPWriting Functions in LISP
First (as usual): understand what’s requiredFirst (as usual): understand what’s required– what are you given?what are you given?– what is the value to return?what is the value to return?
Second: plan how to get resultSecond: plan how to get result– break down into its conditions (if any)break down into its conditions (if any)– identify easy casesidentify easy cases– break harder cases down into partsbreak harder cases down into parts
Functions and ListsFunctions and Lists
List argument generally needs to be broken List argument generally needs to be broken into partsinto parts– (first L) – operate on this directly(first L) – operate on this directly– (rest L) – recur on this(rest L) – recur on this
Mapped parts need to be re-combinedMapped parts need to be re-combined– maybe some math function – atomic resultmaybe some math function – atomic result– usually using CONS – list resultusually using CONS – list result
Implementing a PlanImplementing a Plan
Plan is in steps:Plan is in steps:– calculate thiscalculate this– use it to calculate thatuse it to calculate that
All must be combined into All must be combined into oneone function call function call Early calculations become arguments for Early calculations become arguments for
later oneslater ones– will evaluate from the inside outwill evaluate from the inside out
Plus-1 List: ImperativePlus-1 List: Imperative
Add one to each element of a listAdd one to each element of a listplus1List(L)plus1List(L)
if (L == nil)if (L == nil)return nil;return nil;
elseelsevar newFirst var newFirst first(L) + 1; first(L) + 1;var newRest var newRest plus1List(rest(L)); plus1List(rest(L));return cons(newFirst, newRest);return cons(newFirst, newRest);
variables not necessary
Plus-1 List: ImperativePlus-1 List: Imperative
Add one to each element of a listAdd one to each element of a listplus1List(L)plus1List(L)
if (L == nil)if (L == nil)return nil;return nil;
elseelsereturn cons(first(L) + 1,return cons(first(L) + 1,
plus1List(rest(L)));plus1List(rest(L)));
replace conditional command with conditional expression
Plus-1 List: ImperativePlus-1 List: Imperative
Add one to each element of a listAdd one to each element of a listplus1List(L)plus1List(L)
returnreturn (L == nil) ?(L == nil) ?nilnil
::cons(first(L) + 1, cons(first(L) + 1,
plus1List(rest(L)));plus1List(rest(L)));
now functional: rewrite to LISP
Plus-1 List: LISPPlus-1 List: LISP
Add one to each element of a listAdd one to each element of a list(defun plus1List (L)(defun plus1List (L)
(if (null L)(if (null L)nilnil
(cons (+ (first L) 1)(cons (+ (first L) 1) (plus1List (rest L)))))(plus1List (rest L)))))
make more “idiomatic”
Plus-1 List: LISPPlus-1 List: LISP
Add one to each element of a listAdd one to each element of a list(defun plus1List L(defun plus1List L
(unless (null L)(unless (null L)(cons (+ (first L) 1)(cons (+ (first L) 1)
(plus1List (rest L)))))(plus1List (rest L)))))
(unless (null Arg)(cons (…(first Arg)…)
(…(rest Arg)…)))
programming idiomtranslating a list
Functional AbstractionFunctional Abstraction
Complicated (or repeated) steps should get Complicated (or repeated) steps should get their own function definitionstheir own function definitions– apply same process againapply same process again– understand what understand what youyou want out of the function want out of the function
(don’t let the code control you)(don’t let the code control you) Laziness is a virtueLaziness is a virtue
– leave it for laterleave it for later– but make sure you understand it, firstbut make sure you understand it, first
ExampleExample
Standard deviation (population)Standard deviation (population)– square root of the average of the deviationssquare root of the average of the deviations– given a list of numbers, returns a numbergiven a list of numbers, returns a number
Functional abstractionFunctional abstraction– square root is built in, average we can buildsquare root is built in, average we can build– deviations??? Time to be lazy!deviations??? Time to be lazy!
(defun stdevp (L) (sqrt (average (deviations L))))(defun stdevp (L) (sqrt (average (deviations L))))
Sub-ProblemsSub-Problems
AverageAverage– given a list of numbers, return a numbergiven a list of numbers, return a number– add up the numbers, divide by the # of numbersadd up the numbers, divide by the # of numbers– left as an exerciseleft as an exercise
DeviationsDeviations– deviation = difference from average, squareddeviation = difference from average, squared– given a list of #s, return another list of #sgiven a list of #s, return another list of #s
DeviationsDeviations
Need the average of the listNeed the average of the list– use the average function: use the average function: (average L)(average L)
Need to find the deviation for every element Need to find the deviation for every element in the list – in the list – itsits difference from the average difference from the average– time to be lazy again – another functiontime to be lazy again – another function– given a list & its average, return list of given a list & its average, return list of
deviationsdeviations– (deviation-list L (average L))(deviation-list L (average L))
Deviation ListDeviation List
Need to process a list & return a listNeed to process a list & return a list– break down list (using first & rest)break down list (using first & rest)– calculate deviation (separate function on first, calculate deviation (separate function on first,
recursion on rest)recursion on rest)– reconstruct list (using cons)reconstruct list (using cons)
Unless the list is empty, of courseUnless the list is empty, of course(unless (null L) (cons (…(first L)…) (…(rest L)…)))(unless (null L) (cons (…(first L)…) (…(rest L)…)))
Calculation of deviation of first
Calculation of deviations of rest
Calculating a Single DeviationCalculating a Single Deviation
Given a number and the mean, return a Given a number and the mean, return a number (its deviation)number (its deviation)– their difference, squaredtheir difference, squared– use expt for squaring (expt x 2) = xuse expt for squaring (expt x 2) = x22
(defun calculate-deviation (Value Mean)(defun calculate-deviation (Value Mean)
(expt (– Value Mean) 2))(expt (– Value Mean) 2))
List of DeviationsList of Deviations
(defun deviation-list (L M)(defun deviation-list (L M)(unless (null L)(unless (null L)
(cons(cons(calculate-deviation (first L) M)(calculate-deviation (first L) M)(deviation-list (rest L) M)(deviation-list (rest L) M)
)) )) ))
(defun deviations (L)(defun deviations (L)(deviation-list L (average L)))(deviation-list L (average L)))
Function CallFunction Call
Calculate standard deviation (population) of the Calculate standard deviation (population) of the list (5 10 15)list (5 10 15)
> > (stdevp ‘(5 10 15))(stdevp ‘(5 10 15))
(sqrt (average (deviations ‘(5 10 15))))(sqrt (average (deviations ‘(5 10 15))))
(average (deviations ‘(5 10 15)))(average (deviations ‘(5 10 15)))
(deviations ‘(5 10 15))(deviations ‘(5 10 15))
(deviation-list ‘(5 10 15) (average ‘(5 10 15)))(deviation-list ‘(5 10 15) (average ‘(5 10 15)))
= (deviation-list ‘(5 10 15) 10)= (deviation-list ‘(5 10 15) 10)
Function Call (cont.)Function Call (cont.)
(deviation-list ‘(5 10 15) 10)(deviation-list ‘(5 10 15) 10)
(unless (null ‘(5 10 15)) (…))(unless (null ‘(5 10 15)) (…))
= (unless NIL (cons (…) (…)))= (unless NIL (cons (…) (…)))
(cons (calculate-deviation …) (…))(cons (calculate-deviation …) (…))
(calculate-deviation (first ‘(5 10 15)) 10)(calculate-deviation (first ‘(5 10 15)) 10)
= (calculate-deviation 5 10)= (calculate-deviation 5 10)
(expt (– 10 5) 2) = 25(expt (– 10 5) 2) = 25
= (cons 25 (deviation-list (rest ‘(5 10 15)) 10))= (cons 25 (deviation-list (rest ‘(5 10 15)) 10))
Function Call (cont.)Function Call (cont.)
(deviation-list ‘(10 15) 10)(deviation-list ‘(10 15) 10)
(unless (null ‘(10 15)) (…))(unless (null ‘(10 15)) (…))
= (unless NIL (cons (…) (…)))= (unless NIL (cons (…) (…)))
(cons (calculate-deviation …) (…))(cons (calculate-deviation …) (…))
(calculate-deviation (first ‘(10 15)) 10)(calculate-deviation (first ‘(10 15)) 10)
= (calculate-deviation 10 10)= (calculate-deviation 10 10)
(expt (– 10 10) 2) = 0(expt (– 10 10) 2) = 0
= (cons 0 (deviation-list (rest ‘(10 15)) 10))= (cons 0 (deviation-list (rest ‘(10 15)) 10))
Function Call (cont.)Function Call (cont.)
(deviation-list ‘(15) 10)(deviation-list ‘(15) 10)
(unless (null ‘(15)) (…))(unless (null ‘(15)) (…))
= (unless NIL (cons (…) (…)))= (unless NIL (cons (…) (…)))
(cons (calculate-deviation …) (…))(cons (calculate-deviation …) (…))
(calculate-deviation (first ‘(15)) 10)(calculate-deviation (first ‘(15)) 10)
= (calculate-deviation 15 10)= (calculate-deviation 15 10)
(expt (– 10 15) 2) = 25(expt (– 10 15) 2) = 25
= (cons 25 (deviation-list (rest ‘(15)) 10))= (cons 25 (deviation-list (rest ‘(15)) 10))
Function Call (cont.)Function Call (cont.)
(deviation-list ‘() 10)(deviation-list ‘() 10)
(unless (null ‘()) (…))(unless (null ‘()) (…))
= (unless T (cons (…) (…))) = NIL= (unless T (cons (…) (…))) = NIL
== (cons 25 NIL) = (25)(cons 25 NIL) = (25)
== (cons 0 ‘(25)) = (0 25)(cons 0 ‘(25)) = (0 25)
== (cons 25 ‘(0 25)) = (25 0 25)(cons 25 ‘(0 25)) = (25 0 25)
== (average ‘(25 0 25)) = 16.6667(average ‘(25 0 25)) = 16.6667
== (sqrt 16.6667) = 4.0825(sqrt 16.6667) = 4.0825
Tweaking the CodeTweaking the Code
Deviations just calls deviation-list with own Deviations just calls deviation-list with own argument plus anotherargument plus another
Could be combined into one functionCould be combined into one function– make the mean an optional argumentmake the mean an optional argument– default value – average of the given listdefault value – average of the given list
(defun deviations (L &optional (M (average L))) …)(defun deviations (L &optional (M (average L))) …) Will call average if & only if no mean givenWill call average if & only if no mean given
Combined Deviations CodeCombined Deviations Code
(defun deviations (L &optional (M (average L)))(defun deviations (L &optional (M (average L)))(unless (null L)(unless (null L)
(cons(cons(calculate-deviation (first L) M)(calculate-deviation (first L) M)(deviations (rest L) M)(deviations (rest L) M)
)) )) )) Note: important to pass M in recursive callNote: important to pass M in recursive call
– else calculates average of (10 15) = else calculates average of (10 15) = wrongwrong
Optional ParametersOptional Parameters
Use &optional in parameter listUse &optional in parameter list– everything before &optional is requiredeverything before &optional is required– if not given use NIL – or default value (next)if not given use NIL – or default value (next)
> > (defun opt-args (a &optional b c) (list a b c))(defun opt-args (a &optional b c) (list a b c))
OPT-ARGSOPT-ARGS
> > (list (opt-args 1) (opt-args 2 3) (opt-args 4 5 6))(list (opt-args 1) (opt-args 2 3) (opt-args 4 5 6))
((1 NIL NIL) (2 3 NIL) (4 5 6))((1 NIL NIL) (2 3 NIL) (4 5 6))
Default ValuesDefault Values
For optional argumentsFor optional arguments– list with parameter name & default valuelist with parameter name & default value– default calculated at call timedefault calculated at call time
> > (defun def-args (a &optional (b 5)) (list a b))(defun def-args (a &optional (b 5)) (list a b))
DEF-ARGSDEF-ARGS
> > (list (def-args 1) (def-args 2 3))(list (def-args 1) (def-args 2 3))
((1 5) (2 3))((1 5) (2 3))
CorrelationCorrelation
Write a function to calculate the correlation Write a function to calculate the correlation between two listsbetween two lists– the two lists must be the same lengththe two lists must be the same length
UnderstandingUnderstanding– given two lists (same length)given two lists (same length)– returns a numberreturns a number– formula to followformula to follow
Calculating a CorrelationCalculating a Correlation
Complicated formula requires:Complicated formula requires:– length of lists (N)length of lists (N)– sums of lists (Sx and Sy)sums of lists (Sx and Sy)– dot product of the two lists (Sxy)dot product of the two lists (Sxy)– sums of squares of lists (Sxx and Syy)sums of squares of lists (Sxx and Syy)
Result isResult is(N*Sxy – Sx*Sy)(N*Sxy – Sx*Sy)
sqrt((N*Sxx) – (Sx)sqrt((N*Sxx) – (Sx)22)*(N*Syy – (Sy))*(N*Syy – (Sy)22))))
What Do We Need?What Do We Need?
Functions that calculate:Functions that calculate:– length of a listlength of a list– sum of a listsum of a list– dot product of two listsdot product of two lists– sum of squares of listsum of squares of list
Assume We Have ThemAssume We Have Them
Write the result calculation functionWrite the result calculation function
Write the main functionWrite the main function– N = length of lists (must be same for both)N = length of lists (must be same for both)– Sx = sum of list 1Sx = sum of list 1stst list, Sy = sum of second list, Sy = sum of second– Sxy = dot product of listsSxy = dot product of lists– Sxx = sums of squares of 1Sxx = sums of squares of 1stst list, Syy = ditto 2 list, Syy = ditto 2ndnd
(N*Sxy – Sx*Sy)(N*Sxy – Sx*Sy)sqrt((N*Sxx) – (Sx)sqrt((N*Sxx) – (Sx)22)*(N*Syy – (Sy))*(N*Syy – (Sy)22))))
Now for the HelpersNow for the Helpers
Already have the length function built inAlready have the length function built in Write the sum of a list functionWrite the sum of a list function Write the dot product functionWrite the dot product function
– (1 2 3) * (4 5 6) = (1*4)+(2*5)+(3*6) = 32(1 2 3) * (4 5 6) = (1*4)+(2*5)+(3*6) = 32 Write the sum of squares functionWrite the sum of squares function
– note: can use dot product functionnote: can use dot product function
Final ResultFinal Result
(defun correlation (Xs Ys) …)(defun correlation (Xs Ys) …)
(defun correlation-calc (N Sx Sy Sxy Sxx Sxy) …)(defun correlation-calc (N Sx Sy Sxy Sxx Sxy) …)
(defun sum-of-list (L) …)(defun sum-of-list (L) …)
(defun dot-product (Xs Ys) …)(defun dot-product (Xs Ys) …)
(defun sum-of-squares (L) …)(defun sum-of-squares (L) …)
> > (correlation ‘(5 10 15) ‘(3 6 12))(correlation ‘(5 10 15) ‘(3 6 12))
0.9890.989
ExerciseExercise
Write a function that calculates the Write a function that calculates the correlation of a list of pairscorrelation of a list of pairs– (correlate-pairs ‘((5 3) (10 6) (15 12))) => 0.989(correlate-pairs ‘((5 3) (10 6) (15 12))) => 0.989– list of (X Y) pairslist of (X Y) pairs
Use the correlation function from last timeUse the correlation function from last time– (correlation ‘(5 10 15) ‘(3 6 12)) => 0.989(correlation ‘(5 10 15) ‘(3 6 12)) => 0.989– only difference is the form of the dataonly difference is the form of the data– ((write it in two lines! (hint: be lazy)write it in two lines! (hint: be lazy)))
ExerciseExercise
Use the list translation programming idiom Use the list translation programming idiom we discussed earlier to write the rest of the we discussed earlier to write the rest of the support functions for our new correlations support functions for our new correlations functionfunction– translate list of XY pairs into a list of Xstranslate list of XY pairs into a list of Xs– translate list of XY pairs into a list of Ystranslate list of XY pairs into a list of Ys
Next TimeNext Time
Control over listsControl over lists– Chapter 6Chapter 6