operating on lists chapter 6. firsts and seconds n transforming list of pairs into two lists...
TRANSCRIPT
Operating on ListsOperating on Lists
Chapter 6Chapter 6
Firsts and SecondsFirsts and Seconds
Transforming list of pairs into two listsTransforming list of pairs into two lists– (firsts ‘((1 5) (2 6) (3 7))) (firsts ‘((1 5) (2 6) (3 7))) (1 2 3) (1 2 3)– (seconds ‘((1 5) (2 6) (3 7))) (seconds ‘((1 5) (2 6) (3 7))) (5 6 7) (5 6 7)
Similar codeSimilar code(defun seconds (L)(defun seconds (L)
(unless (null L)(unless (null L)(cons (second (first L)) (seconds (rest (cons (second (first L)) (seconds (rest
L)))))L)))))– replace “second” with “first” for firstsreplace “second” with “first” for firsts
Transforming a ListTransforming a List
Programming clichéProgramming cliché– transform a list into another listtransform a list into another list
(defun <list-change> (theList)(defun <list-change> (theList)(unless (null theList)(unless (null theList)
(cons (<element-change> (first theList))(cons (<element-change> (first theList))(<list-change> (rest theList)))))(<list-change> (rest theList)))))
Applies <element-change> to each elementApplies <element-change> to each element– <element-change> = second, for example<element-change> = second, for example
Transforming a ListTransforming a List
Programming clichéProgramming cliché– transform a list into another listtransform a list into another list
(defun <list-change> (theList)(defun <list-change> (theList)(unless (null theList)(unless (null theList)
(cons (<element-change> (first theList))(cons (<element-change> (first theList))(<list-change> (rest theList)))))(<list-change> (rest theList)))))
Applies <element-change> to each elementApplies <element-change> to each element– <element-change> = second, for example<element-change> = second, for example
firstsfirsts
firstsfirstsfirstfirst
Transforming a ListTransforming a List
Programming clichéProgramming cliché– transform a list into another listtransform a list into another list
(defun <list-change> (theList)(defun <list-change> (theList)(unless (null theList)(unless (null theList)
(cons (<element-change> (first theList))(cons (<element-change> (first theList))(<list-change> (rest theList)))))(<list-change> (rest theList)))))
Applies <element-change> to each elementApplies <element-change> to each element– <element-change> = second, for example<element-change> = second, for example
secondsseconds
secondssecondssecondsecond
MAPCARMAPCAR
A built in function for transforming listsA built in function for transforming lists– mapmap each element – each element – carcar to get an element to get an element
(defun <list-change> (theList)(defun <list-change> (theList)
(mapcar #’<element-change> theList))(mapcar #’<element-change> theList)) Applies <element-change> to each element Applies <element-change> to each element
of theListof theList Note the way the function appears: #’Note the way the function appears: #’namename
Using MAPCARUsing MAPCAR
> > (mapcar #’first ‘((1 5) (2 6) (3 7)))(mapcar #’first ‘((1 5) (2 6) (3 7)))
(1 2 3)(1 2 3)
> > (mapcar #’second ‘((1 5) (2 6) (3 7)))(mapcar #’second ‘((1 5) (2 6) (3 7)))
(5 6 7)(5 6 7)
> > (defun square (N) (expt N 2))(defun square (N) (expt N 2))
SQUARESQUARE
> > (mapcar #’square ‘(1 2 3 4 5 6 10))(mapcar #’square ‘(1 2 3 4 5 6 10))
(1 4 9 16 25 36 100)(1 4 9 16 25 36 100)
MAPCAR MAPCAR vs.vs. Recursion Recursion
(defun square-all (L)(defun square-all (L)
(unless (null L)(unless (null L)
(cons (square (first L))(cons (square (first L))
(square-all (rest L)))))(square-all (rest L))))) Mapcar version more conciseMapcar version more concise
– easier to readeasier to read– more efficientmore efficient– performs exactly the same taskperforms exactly the same task
(defun square-all (L)(defun square-all (L)
(mapcar #’square L))(mapcar #’square L))
ExerciseExercise
> > (mapcar #’third ‘((1 2 3) (a b c) (do re mi)))(mapcar #’third ‘((1 2 3) (a b c) (do re mi)))
> > (mapcar #’fourth ‘((1 2 3 4 5) (x y z)))(mapcar #’fourth ‘((1 2 3 4 5) (x y z)))
> > (mapcar #’oddp ‘(1 2 3 4 5 6 7))(mapcar #’oddp ‘(1 2 3 4 5 6 7))
> > (mapcar #’list ‘(a b c d e))(mapcar #’list ‘(a b c d e))
> > (defun sum-list (L)(defun sum-list (L)(if (null L) 0 (+ (first L) (sum-list (rest (if (null L) 0 (+ (first L) (sum-list (rest
L)))))L)))))
> > (mapcar #’sum-list ‘((1 2 3 4) (5 6 7) (8 5 2)))(mapcar #’sum-list ‘((1 2 3 4) (5 6 7) (8 5 2)))
““Helper” FunctionsHelper” Functions
Recall the function that calculates the Recall the 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– used the correlation function from last timeused the correlation function from last time(defun correlate-pairs (XYs)(defun correlate-pairs (XYs)
(correlation (firsts XYs) (seconds XYs)))(correlation (firsts XYs) (seconds XYs))) Needed to define Needed to define firsts firsts and and secondsseconds as as
separate functionsseparate functions
Avoiding HelpersAvoiding Helpers
Use MAPCAR and avoid having to make Use MAPCAR and avoid having to make those functionsthose functions
(defun correlate-pairs (XYs)(defun correlate-pairs (XYs)
(correlation (mapcar #’first XYs)(correlation (mapcar #’first XYs)
(mapcar #’second XYs)))(mapcar #’second XYs)))
Multi-Argument MAPCARMulti-Argument MAPCAR
May take a third, fourth, …, argumentMay take a third, fourth, …, argument Function argument is applied to firsts of all Function argument is applied to firsts of all
lists, then seconds, then thirds, &so on…lists, then seconds, then thirds, &so on…> > (mapcar #’+ ‘(1 2 3) ‘(4 5 6) ‘(7 8 9))(mapcar #’+ ‘(1 2 3) ‘(4 5 6) ‘(7 8 9))
(1 (1 2 2 3)3)(4 (4 5 5 6)6)
++ (7 (7 8 8 9)9)
(( 1212 1515 18)18)
ExerciseExercise
> > (mapcar #’* ‘(1 2 7) ‘(3 4 6))(mapcar #’* ‘(1 2 7) ‘(3 4 6))
> > (mapcar #’expt ‘(1 2 3 4 5) ‘(5 4 3 2 1))(mapcar #’expt ‘(1 2 3 4 5) ‘(5 4 3 2 1))
> > (mapcar #’< ‘(1 2 3 4 5) ‘(2 4 6 8 10) ‘(5 6 7 8 9))(mapcar #’< ‘(1 2 3 4 5) ‘(2 4 6 8 10) ‘(5 6 7 8 9))
> > (mapcar #’append ‘((1 2) (a b)) ‘((x y) (do re)))(mapcar #’append ‘((1 2) (a b)) ‘((x y) (do re)))
> > (defun distance (P1 P2) (abs (– P1 P2)))(defun distance (P1 P2) (abs (– P1 P2)))
> > (mapcar #’distance ‘(1 2 3 4) ‘(5 4 3 2))(mapcar #’distance ‘(1 2 3 4) ‘(5 4 3 2))
Other List Handling FunctionsOther List Handling Functions
Some other common tasks have been abstracted into Some other common tasks have been abstracted into built-in functionsbuilt-in functions– remove-ifremove-if returns a shorter listreturns a shorter list– remove-if-notremove-if-not returns a shorter listreturns a shorter list– count-ifcount-if counts matching items in the listcounts matching items in the list– find-iffind-if returns first matching itemreturns first matching item
Remove-If & Remove-If-NotRemove-If & Remove-If-Not
Use a predicate to eliminate/select itemsUse a predicate to eliminate/select items> > (remove-if #’oddp ‘(1 2 3 4 5 6 7))(remove-if #’oddp ‘(1 2 3 4 5 6 7))
(2 4 6)(2 4 6)
> > (remove-if-not #’oddp ‘(1 2 3 4 5 6 7))(remove-if-not #’oddp ‘(1 2 3 4 5 6 7))
(1 3 5 7)(1 3 5 7)
Functions, Not AssignmentsFunctions, Not Assignments
Remove-if & remove-if-not do not modify Remove-if & remove-if-not do not modify their argumenttheir argument
> > (setf aList ‘(1 2 3 4 5 6 7))(setf aList ‘(1 2 3 4 5 6 7))(1 2 3 4 5 6 7)(1 2 3 4 5 6 7)> > (remove-if #’oddp aList)(remove-if #’oddp aList)(2 4 6)(2 4 6)> > aListaList(1 2 3 4 5 6 7)(1 2 3 4 5 6 7)
Use (setf Var (remove-if … Var)) tochange the value by removing items
Count-IfCount-If
Use a predicate to count itemsUse a predicate to count items> > (count-if #’oddp ‘(1 2 3 4 5 6 7))(count-if #’oddp ‘(1 2 3 4 5 6 7))
44
> > (count-if #’evenp ‘(1 2 3 4 5 6 7))(count-if #’evenp ‘(1 2 3 4 5 6 7))
33 Equivalent to (length (remove-if-not F L))Equivalent to (length (remove-if-not F L))
– but more efficientbut more efficient
Find-IfFind-If
Returns first item that satisfies the predicateReturns first item that satisfies the predicate> > (find-if #’oddp ‘(2 3 4 5 6 7))(find-if #’oddp ‘(2 3 4 5 6 7))
33
> > (find-if #’evenp ‘(2 3 4 5 6 7))(find-if #’evenp ‘(2 3 4 5 6 7))
22
ExercisesExercises
> > (remove-if #’numberp ‘(a 2 c (i v) 5))(remove-if #’numberp ‘(a 2 c (i v) 5))
> > (remove-if-not #’atom ‘(a 2 c (i v) 5))(remove-if-not #’atom ‘(a 2 c (i v) 5))
> > (count-if #’symbolp ‘(a 2 c (i v) 5))(count-if #’symbolp ‘(a 2 c (i v) 5))
> > (defun in-range (N) (<= 0 N 100))(defun in-range (N) (<= 0 N 100))
> > (remove-if-not #’in-range ‘(110 75 –10 44 50))(remove-if-not #’in-range ‘(110 75 –10 44 50))
> > (find-if #’in-range ‘(110 75 –10 44 50))(find-if #’in-range ‘(110 75 –10 44 50))
> > (find-if #’listp ‘(a 2 c (i v) 5))(find-if #’listp ‘(a 2 c (i v) 5))
Function Calling FunctionsFunction Calling Functions
FuncallFuncall and and applyapply call functions call functions> > (funcall #’+ 1 2 3 4 5 6)(funcall #’+ 1 2 3 4 5 6)
2121
> > (apply #’+ ‘(1 2 3 4 5 6))(apply #’+ ‘(1 2 3 4 5 6))
2121 Both same as (+ 1 2 3 4 5 6)Both same as (+ 1 2 3 4 5 6)
Funcall, Apply & EvalFuncall, Apply & Eval
(funcall #’+ 1 2 3)(funcall #’+ 1 2 3) == (+ 1 2 3)(+ 1 2 3)– four argumentsfour arguments– function + function + its its argumentsarguments
(apply #’+ ‘(1 2 3))(apply #’+ ‘(1 2 3)) == (+ 1 2 3)(+ 1 2 3)– two argumentstwo arguments– function + function + list of its list of its argumentsarguments
(eval ‘(+ 1 2 3))(eval ‘(+ 1 2 3)) == (+ 1 2 3)(+ 1 2 3)– one argument: form to be evaluatedone argument: form to be evaluated
Applying Functions to ListsApplying Functions to Lists
Apply used to apply functions to listsApply used to apply functions to lists– list passed as an argument, perhapslist passed as an argument, perhaps– avoid recursive function callsavoid recursive function calls
> > (defun sum-list (L) (apply #’+ L))(defun sum-list (L) (apply #’+ L))
> > (sum-list ‘(1 2 3 4 5 6))(sum-list ‘(1 2 3 4 5 6))
2121
APPLY APPLY vs.vs. Recursion Recursion
(defun sum-list (L)(defun sum-list (L)
(if (null L)(if (null L) 00
(+ (first L)(+ (first L)
(sum-list (rest L)))))(sum-list (rest L))))) Apply version more conciseApply version more concise
– easier to readeasier to read– more efficientmore efficient– perform exactly the same taskperform exactly the same task
(defun sum-list (L)(defun sum-list (L)
(apply #’+ L))(apply #’+ L))
Dot ProductsDot Products
We defined a dot-product function last timeWe defined a dot-product function last time– (dot-product ‘(5 10 15) ‘(3 6 9)) => 210(dot-product ‘(5 10 15) ‘(3 6 9)) => 210– 5*3 + 10*6 + 15*9 = 15 + 60 + 135 = 2105*3 + 10*6 + 15*9 = 15 + 60 + 135 = 210(defun dot-product (Xs Ys)(defun dot-product (Xs Ys)
(if (null Xs) 0 (+ (* (first Xs) (first Ys))(if (null Xs) 0 (+ (* (first Xs) (first Ys))(dot-product (rest Xs) (rest (dot-product (rest Xs) (rest
Ys))))Ys)))) Can be written using apply and mapcarCan be written using apply and mapcar
– use mapcar to multiply each pair of numbersuse mapcar to multiply each pair of numbers– use apply to add up the resulting listuse apply to add up the resulting list
Dot ProductDot Product
(mapcar #’* ‘(5 10 15) ‘(3 6 9))(mapcar #’* ‘(5 10 15) ‘(3 6 9)) => (15 60 135) => (15 60 135)
(apply #’+ ‘(15 60 135)) => 210(apply #’+ ‘(15 60 135)) => 210(defun dot-product (L1 L2)(defun dot-product (L1 L2)
(apply #’+ (mapcar #’* L1 L2)))(apply #’+ (mapcar #’* L1 L2)))
Plus 1 List RevisitedPlus 1 List Revisited
Wanted to add 1 to each element of a listWanted to add 1 to each element of a list(defun plus1List (L)(defun plus1List (L)
(unless (null L)(unless (null L)(cons (+ 1 (first L)) (plus1List (rest L)))))(cons (+ 1 (first L)) (plus1List (rest L)))))
Using MAPCAR:Using MAPCAR:(defun plus1List (L)(defun plus1List (L)
(mapcar #’1+ L))(mapcar #’1+ L))– 1+ is the “add 1” function1+ is the “add 1” function
Plus 2 ListPlus 2 List
Suppose we wanted to add 2 insteadSuppose we wanted to add 2 instead(defun plus2List (L)(defun plus2List (L)
(unless (null L)(unless (null L)(cons (+ 2 (first L)) (plus1List (rest L)))))(cons (+ 2 (first L)) (plus1List (rest L)))))
There is no There is no 2+2+ function function– need to write our ownneed to write our own
(defun 2+ (N) (+ N 2))(defun 2+ (N) (+ N 2))– how can we avoid that?how can we avoid that?
Lambda (Lambda () in LISP) in LISP
Lambda expression is a way of specifying a Lambda expression is a way of specifying a function without giving it a namefunction without giving it a name
Very much like defun – leave out the nameVery much like defun – leave out the name(defun add-10 (x) (+ x 10))(defun add-10 (x) (+ x 10))
(lambda (x) (+ x 10))(lambda (x) (+ x 10)) Both give the same functionBoth give the same function
– but defun gives it a name, toobut defun gives it a name, too
Using Lambda ExpressionsUsing Lambda Expressions
Can be used where-ever a function isCan be used where-ever a function is– function arguments, in particularfunction arguments, in particular
> > (mapcar (lambda (x) (+ x 10)) ‘(1 2 3 4))(mapcar (lambda (x) (+ x 10)) ‘(1 2 3 4))(11 12 13 14)(11 12 13 14)
> > ((lambda (x) (+ x 10)) 5)((lambda (x) (+ x 10)) 5)1515 Note: text has #’ in front of the Note: text has #’ in front of the expr. expr.
– may be necessary in some LISPsmay be necessary in some LISPs
ExercisesExercises
Evaluate the following:Evaluate the following:> > (mapcar (lambda (x) (* x x)) ‘(2 4 6 8))(mapcar (lambda (x) (* x x)) ‘(2 4 6 8))
> > ((lambda (x) (numberp x)) ‘(a 2 c (i v) 5))((lambda (x) (numberp x)) ‘(a 2 c (i v) 5))
> > (mapcar(mapcar(lambda (x) (and (numberp x) (evenp x)))(lambda (x) (and (numberp x) (evenp x)))‘(a 2 c (i v) 5))‘(a 2 c (i v) 5))
ExerciseExercise
Write a function using mapcar and a lambda Write a function using mapcar and a lambda expression to double every element of a listexpression to double every element of a list
> > (double-all ‘(3 5 8 18))(double-all ‘(3 5 8 18))
(6 10 16 36)(6 10 16 36)
Lambda VariablesLambda Variables
Lambda expressions use variablesLambda expressions use variables– parameter listparameter list– ““open” variablesopen” variables
Looks for nearest definition of the variableLooks for nearest definition of the variable– a parameter of this lambda expressiona parameter of this lambda expression– a parameter of an enclosing lambda/defuna parameter of an enclosing lambda/defun
Open VariablesOpen Variables
We can write a function that adds a given We can write a function that adds a given amount to every element of a listamount to every element of a list
> > (add-to-each 5 ‘(2 4 6 9))(add-to-each 5 ‘(2 4 6 9))
(7 9 11 14)(7 9 11 14) Can use first parameter as “open” in lambdaCan use first parameter as “open” in lambda> > (defun add-to-each (Amt Lst)(defun add-to-each (Amt Lst)
(mapcar (lambda (x) (+ Amt x)) Lst))(mapcar (lambda (x) (+ Amt x)) Lst))
ExerciseExercise
Write a function using mapcar and a lambda Write a function using mapcar and a lambda expression that calculates the Nexpression that calculates the N thth power of power of every element of a list (where N is given as every element of a list (where N is given as the second parameter)the second parameter)
> > (nth-power-each ‘(1 2 3 4 5) 3)(nth-power-each ‘(1 2 3 4 5) 3)
(1 8 27 64 125)(1 8 27 64 125)
ExerciseExercise
Defun this function:Defun this function:– (mathify #’+ 5 ‘(1 2 3 4))(mathify #’+ 5 ‘(1 2 3 4)) ;; add 5 to each;; add 5 to each(6 7 8 9)(6 7 8 9)– (mathify #’* 4 ‘(1 2 3 4))(mathify #’* 4 ‘(1 2 3 4)) ;; multiply each by 4;; multiply each by 4(4 8 12 16)(4 8 12 16)– (mathify #’/ 10 ‘(1 2 3 4))(mathify #’/ 10 ‘(1 2 3 4)) ;; divide each by ;; divide each by
1010(1/10 1/5 3/10 2/5)(1/10 1/5 3/10 2/5)– break it into stepsbreak it into steps!!
Next TimeNext Time
Data AbstractionData Abstraction– chapter 6chapter 6