<<

Overview

FunctionalFunctional „In a functional , functions are first class objects. Programming „You can create them, put them in data Programming structures, compose them, specialize them, apply the to arguments, etc. andand LispLisp „We’ll look at how things are done in Lisp

1 UMBC an Honors University in Maryland 2

Concepts and functions eval

„Eval „ Remember: Lisp code is just an s-expression „Apply „ You can call Lisp’s evaluation process with the eval function. „Funcall > (setf s1 '(second '(one two three))) „Lambda (second '(ONE TWO THREE))

> (eval s1) (cdr (quote (a . b))) TWO (quote (a . b)) > (eval (list 'cdr (car '((quote (a . b)) )))) B UMBC UMBC an Honors University in Maryland 3 an Honors University in Maryland 4

1 Functions as objects Functions as objects „ Just as we can use ‘ as an abbreviation for „ In lisp, functions are regular objects, like Just as we can use ‘ as an abbreviation for symbols, or strings, or lists. quote, we can use #’ as an abbreviation for function: „ If we give the name of a function to function, function: it will return the associated object. > #’+ „ Like quote, function is a special operator, so # we don’t have to quote the argument: „ This abbreviation is known as sharp-quote. > (defun add1 (n) (+ n 1)) „ Like any other kind of object, we can pass ADD1 functions as arguments. > (function +) # „ One function that takes a function as an > (function add1) argument is apply. # UMBC UMBC an Honors University in Maryland 5 an Honors University in Maryland 6

Apply Funcall

„ Apply takes a function and a list of arguments for it, and returns the result of applying the „The function funcall is like apply but does function to the arguments: not need the arguments to be packaged in > (apply #’+ ‘(1 2 3)) a list: 6 > (funcall #’+ 1 2 3) „ It can be given any number of arguments, so 6 long as the last is a list: 6 > (apply #’+ 1 2 ‘(3 4 5)) „It could be written as: 15 (defun funcall (f &rest args) „ A simplified version of apply could be written: (eval (cons f args))) (defun apply (f list) (eval (cons f list))) UMBC UMBC an Honors University in Maryland 7 an Honors University in Maryland 8

2 Lambda Lambda expression

„The defun macro creates a function and „A lambdalambda expressionexpression is a list containing gives it a name. the symbol lambdalambda, followed by a list of „However, functions don’t have to have parameters, followed by a body of zero names, and we don’t need defun to define or more expressions: them. > (setf f (lambda (x) (+ x 1))) „We can refer to functions literally by using # a lambdalambda expressionexpression. > (funcall f 100) „Think of a lambda expression as returning (when evaluated) an anonymous function. 101

UMBC UMBC an Honors University in Maryland 9 an Honors University in Maryland 10

Lambda expression Recap

„ A lambda expression can be considered as „Two ways to make functions specifying an anonymous function. specifying an anonymous function. „ (defun foo (x) (+ x 1)) „ Like an ordinary function name, a lambda Like an ordinary function name, a lambda „ (setf bar (lambda (x) (+ x 1))) expression can be the first element of a function call: „Calling a function > ((lambda (x) (+ x 100)) 1) „ (foo 100) => 101 „ ((lambda (x) (+ x 1) 100) => 101 101 ((lambda (x) (+ x 1) 100) => 101 „ (bar 100) => ??? „ and by affixing a sharp-quote to a lambda expression, we get the corresponding function: „Getting a functional object > (funcall #’(lambda (x) (+ x 100)) 1) „ (function foo) 101 „ (function (lambda (x) (+ x 100))) UMBC UMBC an Honors University in Maryland 11 an Honors University in Maryland 12

3 Who cares? Mapcar and friends

„What good is this, anyway? „Sometimes its useful to apply a function to „Having functions as “first class objects” every element of a list and return a list of allows us to do some interesting things. the results. > (mapcar #’1+ ‘(-1 2 -3)) „As we will see… (0 3 -2) > (mapcar #’abs (mapcar #’1+ ‘‘(-1 2 -3))) (0 3 2) > (mapcar ‘integerp ‘(a 2 (b) -3 nil 4)) (nil t nil t nil t) UMBC UMBC an Honors University in Maryland 13 an Honors University in Maryland 14

Defining mapcar Mapping functions Mapcar has been generalized to functions which „ Mapcar is built in but could be defined take more than one argument > (mapcar #’> ‘(5 3 1 0) ‘(4 4 4 -4)) (defun mapcar (f list) (t nil nil t) (cond ((null list) nil) > (mapcar #'cons '(a b c) '(1 2 3)) ((consp list) ((a . 1) (b . 2) (c . 3)) > (mapcar #’list ‘(a b c) ‘(1 2 3 4)) (cons (funcall f (car list)) ((A 1) (B 2) (C 3)) (mapcar f (cdr list)))) > (mapcar #’(lambda (x y) (* (- x 1)(+ y 1))) (t (error “bad arg to mapcar”)))) ‘(1 2 3) ‘(2 3 4)) (0 4 10) UMBC UMBC an Honors University in Maryland 15 an Honors University in Maryland 16

4 Maplist Every and Some „ every and some take a predicate and one or „ The related function maplist takes the same arguments, but more sequences calls the function on successive CDRs of the lists: „ When given just one sequence, they test > (maplist #’(lambda (x) x) ‘(a b c)) whether the elements satisfy the predicate: ((A B C) (B C) (C)) > (every #’oddp ‘(1 3 5)) > (maplist #'(lambda (x) (cons 'foo x)) '(a b c )) T ((foo a b c d) (foo b c d) (foo c d) (foo d)) > (some #’evenp ‘(1 2 3)) > (maplist #'(lambda (x) (if (member (car x) (cdr x)) 0 1))) T '(a b a c d b c)) „ If given >1 sequences, the predicate must (0 0 1 0 1 1 1) take as many arguments as there are sequences, and arguments are drawn one at a „ mapcan, There is also mapcan, . Use the on-line time from them: the Language to discover what these mapping mapc, and mapl > (every #’> ‘(1 3 5) ‘(0 2 4)) functions do. > (every #’> ‘(1 3 5) ‘(0 2 4)) T UMBC UMBC an Honors University in Maryland 17 an Honors University in Maryland 18

Example: filter Example: reduce (defun filter (function list) ;; returns elements of list for which function is true. ¾ Reduce takes (i) a function, (ii) a final value, and (cond ((null list) nil) (iii) a list ((funcall function (car list)) (cons (car list) ¾ Reduce (+ 0 [v1 v2 v3 … vn]) is just (filter (cdr list) function))) V1 + V2 + V3 + … Vn +0 (t (filter function (cdr list))))) ¾ In Lisp notation: filter > (reduce #’+ 0 ‘(1 2 3 4 5)) > (filter #’evenp ‘(1 2 3 4 5 6 7)) (2 4 6) 15 > (filter #’prime (integers 2 20) ) (reduce #’* 1 ‘(1 2 3 4 5)) (2 3 5 7 11 13 17 19) 120 UMBC UMBC an Honors University in Maryland 19 an Honors University in Maryland 20

5 Example: reduce Examples: reduce

(defun reduce (function final list) (defun copylist (list) (if (null list) (reduce #'cons nil list)) final (funcall function (defun appendlist (list) (first list) (reduce #'append nil list)) (reduce function final (rest list))))) (reduce #'append nil list))

(defun sumlist (list) (reduce #'+ 0 list)) > (appendlist ‘((a b)(1 2)(c d)(3 4))) (defun mullist (list) (reduce #'* 1 list)) (a b 1 2 c d 3 4) UMBC UMBC an Honors University in Maryland 21 an Honors University in Maryland 22

Free variables When are functions defined?

„ Suppose we have a function with a free „Most of the time we use defun, we are variable, like increment in this: defining functions “at the top level” (defun huh (x) (+ x increment) „So free variables are global variables „ If we call (huh 100) what should happen? „ Lisp is lexically scoped, so free variables are „But, lambda expressions allow us to define looked up in the environment in which the functions in a local environment function was defined. „ > (setf increment 1000) „=> the need for closures 1000 > (huh 100) 1100 UMBC UMBC an Honors University in Maryland 23 an Honors University in Maryland 24

6 Closures Closure example > (defun make-counter ( ) „Lisp is a lexically scoped language. (let ((count 0)) „Free variables referenced in a function (lambda ( ) (setf count (1+ count))))) those are looked up in the environment in MAKE-COUNTER which the function is defined. > (setf c (make-counter)) # „ Free variables are those a function (or block) doesn’t create for. > (funcall c) 1 „A closure is a function that remembers the > (funcall c) environment in which it was created. 2 „An environment is just a collection of > (funcall c) variable bindings and their values. 3 UMBC UMBC an Honors University in Maryland 25 an Honors University in Maryland 26

Closure example 2 Closure example 3

> (setf c1 (make-counter)) > (defun make-counter (&optional (increment 1)) # (let ((count 0)) > (setf c2 (make-counter)) (lambda () (setf count (+ count increment))))) # MAKE-COUNTER > (setf c2 (make-counter 2)) > (funcall c1) > (setf c2 (make-counter 2)) # > (funcall c1) > (funcall c2) 2 2 > (funcall c2) > (funcall c2) 1 4 > (funcall c1) 3 UMBC UMBC an Honors University in Maryland 27 an Honors University in Maryland 28

7 SO?

„Closure are quite powerful, as we will see „In effect, they allow you to suspend execution of a thread by creating a function that will resume it „And later call the function to resume computation „We’ll look at this when we look at streams

UMBC UMBC an Honors University in Maryland 29 an Honors University in Maryland 30

8