Presentation is loading. Please wait.

Presentation is loading. Please wait.

Dr. Philip Cannata 1 Programming Languages Chapter 14 – Functional Programming – Lisp.

Similar presentations


Presentation on theme: "Dr. Philip Cannata 1 Programming Languages Chapter 14 – Functional Programming – Lisp."— Presentation transcript:

1 Dr. Philip Cannata 1 Programming Languages Chapter 14 – Functional Programming – Lisp

2 Dr. Philip Cannata 2 Contents 14.1 Functions and the Lambda Calculus 14.2 Scheme 14.2.1 Expressions 14.2.2 Expression Evaluation 14.2.3 Lists 14.2.4 Elementary Values 14.2.5 Control Flow 14.2.6 Defining Functions 14.2.7 Let Expressions 14.2.8 Example: Semantics of Clite 14.2.9 Example: Symbolic Differentiation 14.2.10 Example: Eight Queens 14.3 Haskell

3 Dr. Philip Cannata 3 Overview of Functional Languages They emerged in the 1960’s with Lisp Functional programming mirrors mathematical functions: domain = input, range = output Variables are mathematical symbols: not associated with memory locations. Pure functional programming is state-free: no assignment Referential transparency: a function’s result depends only upon the values of its parameters.

4 Dr. Philip Cannata 4 14.1 Functions and the Lambda Calculus The function Square has R (the reals) as domain and range. Square : R  R Square(n) = n 2 A function is total if it is defined for all values of its domain. Otherwise, it is partial. E.g., Square is total. A lambda expression is a particular way to define a function: LambdaExpression  variable | ( M N) | ( variable. M ) M  LambdaExpression N  LambdaExpression E.g., ( x. x 2 ) represents the Square function.

5 Dr. Philip Cannata 5 Properties of Lambda Expressions In ( x. M), x is bound. Other variables in M are free. A substitution of N for all occurrences of a variable x in M is written M[x  N]. Examples: A beta reduction (( x. M)N) of the lambda expression ( x. M) is a substitution of all bound occurrences of x in M by N. E.g., (( x. x 2 )5) = 5 2

6 Dr. Philip Cannata 6 Lambda Calculus Arithmetic 0 := λ f. λ x. x 1 := λ f. λ x. f x 2 := λ f. λ x. f (f x) 3 := λ f. λ x. f (f (f x)) // 3 is represented as the third power of a function f of x // Notice, each of these (except 0) take a function as an argument and // return a function. SUCC := λ n. λ f. λ x. f (n f x) // successor of n means apply f to x n times and then apply it once more PLUS := λ m. λ n. λ f. λ x. m f (n f x) // apply f to x n times and then apply in m more times MULT := λ m. λ n. m (PLUS n) 0 // add n to 0 m times

7 Dr. Philip Cannata 7 Recursive Lambda Expressions

8 Dr. Philip Cannata 8 Jython Recursive Lambda Expressions

9 Dr. Philip Cannata 9 I have a question regarding static/dynamic typing and binding. I think I understand dynamic typing and binding, but don't really get static. Can you explain static typing/binding, and give an example? The textbook discusses CLite, which only has one method, opposed to the multi-method language we have worked on, and most websites talk about Java, C++, and other object-oriented languages. From the book,it also seems that there is some overlap between binding and typing. I'm not sure what the difference is. I recently finished homework 9 and had a question about scoping. As I understand the test.c.out you provided, it seems like variables in lambda expressions that are not parameters, are bound using whatever the local state looks like at the time of the actual application. For instance, when the lambda is applied inside of the function C, the b variable in the lambda expression is bound to the b variable value in the local scope. As I understand it, this is called dynamic scoping. Another approach would be to bind all the local (non-parameter) lambda variables to values when the lambda is defined. This would yield a different output than the one provided in the homework and, I believe, is called lexical scoping. Is there a reason you chose the scoping rules you did when you assigned this homework? Is there a reason to prefer one scoping mechanism over another in language design? Two questions from students (let ((a 1)) ; binding (1) (let ((f (lambda () (print a)))) (let ((a 2)) ; binding (2) (funcall f)))) int h, i; int C(int a) { int b, c; b = 2; c = a ~ - 17; return a; } int main () { int a, b, l, x, y; bool c; h = 5; a = 3; b = 2; b = (\ x -> x + 2) 33 * 2 + 1; C((\ x -> x + 6) ); y = C((\ x -> x + 6 * b) ); }

10 Dr. Philip Cannata 10 14.2 Scheme A derivative of Lisp Our subset: –omits assignments –simulates looping via recursion –simulates blocks via functional composition Scheme is Turing complete, but Scheme programs have a different flavor We will do Lisp

11 Dr. Philip Cannata 11 Lisp S-expressions $ lisp GCL (GNU Common Lisp) Version(2.5.0) Tue Jan 14 14:23:46 EAST 2003 Licensed under GNU Library General Public License Contains Enhancements by W. Schelter Use (help) to get some basic information on how to use GCL. > (+ 4 5 6 7) 22 > (if (< 1 2) 111 222) 111 > (if (> 1 2) 111 222) 222 > (if t 111 222) 111 > (if f 111 222) Error: The variable F is unbound. Fast links are on: do (si::use-fast-links nil) for debugging Error signalled by IF. Broken at IF. Type :H for Help. >>:r Top level. >(if nil 111 222) 222

12 Dr. Philip Cannata 12 Lisp Lists – car, cdr, cons IBM 704 had CAR (Contents of Address Register) and CDR (Contents of Data Register). >(car '(4 5 6)) 4 >(car (car '((1) (2) (3)))) 1 >(caar '((1) (2) (3))) 1 >(cdr '(4 5 6)) (5 6) >(cadr '(4 5 6)) 5 >(cddr '(4 5 6)) (6) >(caddr '(4 5 6)) 6 >(cons '( a b c) '(1 2 3)) ((A B C) 1 2 3)

13 Dr. Philip Cannata 13 Lisp Let – (let x y expression) > (let n (+ 1 2) (* n 3)) Error: N is not of type LIST. Fast links are on: do (si::use-fast-links nil) for debugging Error signalled by LET. Broken at LET. Type :H for Help. >>:r Top level. >

14 Dr. Philip Cannata 14 Lisp Let – (let x y expression) (let (f n) (* n n) (f 10))

15 Dr. Philip Cannata 15 Lisp Let – (let x y expression) (let (factorial N) (if (= N 0) 1 (* N (factorial (- N 1)))) (factorial 5))

16 Dr. Philip Cannata 16 Lisp Let – (let x y expression) (let (factorial N) (if (= N 0) 1 (* N (factorial (- N 1)))) (factorial 1000))

17 Dr. Philip Cannata 17 head :: [a] -> a head (x:_) = x tail :: [a] -> [a] tail (_:xs) = xs null :: [a] -> Bool null [] = True null (_:_) = False myLast :: [a] -> a myLast [x] = x myLast (_:xs) = myLast xs myInit :: [a] -> [a] myInit [_] = [] myInit (x:xs) = x :myInit xs myLength :: [a] -> Int myLength [] = 0 l myLength (_:l) = 1 + myLength l (defun head (x) (when (listp x) (car x))) (defun tail (x) (cdr x)) (defun my-null (x) (when (and (listp x) (= (length x) 0)) t)) (defun my-last (x) (if (not (cdr x)) (car x) (my-last (cdr x)))) (defun init (x) (when (cdr x) (append (list (car x)) (init (cdr x))))) (defun init-cons (x) (when (cdr x) (cons (car x) (init (cdr x))))) (defun my-length (x) (if (atom x) 0 (1+ (my-length (cdr x))))) head([X|_],X). tail([_|Xs],Xs). null([]). mylast([X],X). mylast([_|Xs],Y) :- mylast(Xs,Y). init([_],[]). init([X|Xs],[X|Ys]) :- init(Xs,Ys). mylength([],0). mylength([_|L],N) :- mylength(L,N0), N is 1+N0. Prolog Haskell Prolog Common Lisp After defining my-last, try: (trace my-last)

18 Dr. Philip Cannata 18 sumList :: (Num a) => [a] -> a sumList [] = 0 sumList (x:xs) = x + sumList xs nth :: Int -> [a] -> a nth 0 (x:_) = x nth n (_:xs) | n > 0 = nth (n-1) xs myTake :: Int -> [a] -> [a] myTake 0 _ = [] myTake _ [] = [] myTake n (x:xs) | n > 0 = x : myTake (n-1) xs myDrop :: Int -> [a] -> [a] myDrop 0 xs = xs myDrop _ [] = [] myDrop n (_:xs) | n > 0 = myDrop (n-1) xs mySplitAt :: Int->[a]->([a],[a]) mySplitAt 0 xs = ([], xs) mySplitAt _ [] = ([],[]) mySplitAt n (x:xs) | n > 0 = (x:xs', xs'') where (xs', xs'') = mySplitAt (n-1) xs (defun sum-list (x) (if (atom x) (if (atom x) 0 (+ (car x) (sum-list (cdr x))))) (+ (car x) (sum-list (cdr x))))) (defun sum-list-loop (x) (loop for i in x summing i)) (loop for i in x summing i)) (defun my-nth (index list) (if (not (= index 0)) (if (not (= index 0)) (my-nth (1- index) (cdr list)) (my-nth (1- index) (cdr list)) (car list))) (car list))) (defun take (num list) (when (> num 0) (when (> num 0) (cons (car list) (take (1- num) (cdr list))))) (cons (car list) (take (1- num) (cdr list))))) (defun drop (num list) (if (> num 0) (if (> num 0) (drop (1- num) (cdr list)) (drop (1- num) (cdr list)) list)) list)) (defun split-at (n list) (if (> n 0))) (if (> n 0))) (defun max-list-recur (list) (max-list-recur-aux list (car list))) (max-list-recur-aux list (car list))) sumList([],0). sumList([X|Xs],N):- sumList(Xs,N0),N is X+N0. mynth(0,[X|_],X). mynth(N,[_|Xs],Y):-N>0, N1 is N-1, mynth(N1,Xs,Y). take(0,_,[]). take(_,[],[]). take(N,[X|Xs],[X|Ys]):-N>0, N1 is N-1,take(N1,Xs,Ys). drop(0,Xs,Xs). drop(_,[],[]). drop(N,[_|Xs],Ys):-N>0, N1 is N-1,drop(N1,Xs,Ys). splitAt(0,Xs,[],Xs). splitAt(_,[],[],[]). splitAt(N,[X|Xs],[X|Xs1],Xs2):- N>0,N1 is N-1, splitAt(N1,Xs,Xs1,Xs2). Prolog Haskell Prolog Common Lisp

19 Dr. Philip Cannata 19 myAppend :: [a] -> [a] -> [a] myAppend [] ys = ys myAppend (x:xs) ys = x : myAppend xs ys myNreverse :: [a] -> [a] myNreverse [] = [] myNreverse (x:xs) = myAppend (myNreverse xs) [x] myReverse :: [a] -> [a] myReverse xs = rev xs [] rev:: [a] -> [a] -> [a] rev [] ys = ys rev (x:xs) y0s = rev xs (x:y0s) (defun my-append (lista listb) (if (not (null lista)) (if (not (null lista)) (cons (car lista) (my-append (cdr lista) listb)) (cons (car lista) (my-append (cdr lista) listb)) listb)) listb)) (defun my-reverse (x) (unless (atom x) (unless (atom x) (append (my-reverse (cdr x)) (list (car x))))) (append (my-reverse (cdr x)) (list (car x))))) myappend([],Ys,Ys). myappend([X|Xs],Ys,[X|Zs]) :- myappend(Xs,Ys,Zs). nreverse([],[]). nreverse([X|Xs],Ys):- nreverse(Xs,Ys1), append(Ys1,[X],Ys). myreverse(Xs,Ys) :- rev(Xs,[],Ys). rev([],Ys,Ys). rev([X|Xs],Y0s,Ys) :- rev(Xs,[X|Y0s],Ys). Prolog Haskell Prolog Common Lisp


Download ppt "Dr. Philip Cannata 1 Programming Languages Chapter 14 – Functional Programming – Lisp."

Similar presentations


Ads by Google