Functional Programming with Scheme Introduction to Functional Programming

  • Slides: 107
Download presentation
Functional Programming with Scheme Introduction to Functional Programming Concepts and the Scheme language. 1

Functional Programming with Scheme Introduction to Functional Programming Concepts and the Scheme language. 1

Introduction q In Theory of Computing, a program is viewed as a function. A

Introduction q In Theory of Computing, a program is viewed as a function. A program maps each input to some output: P: Input Output q deterministic program: the input completely determines the output: output = P(input) q Functional programs puts this model into practice: programs are written in terms of a sequence of functions, typically with nested evaluation: P(input) = (F(g(h(input))) U. . . ) q Evaluating the program produces the output. 2

Characteristics of Functional Lang. based on functions as mappings (as in mathematics) f: Domain

Characteristics of Functional Lang. based on functions as mappings (as in mathematics) f: Domain Range q functions are referentially transparent: n the mapping does not depend on any "state" n value returned depends only on the parameters q functions do not have side effects q "variables" represent values, not memory locations. n in a pure functional language, assignment is not allowed q repetition is done by recursion instead of iteration n can't write "for" or "while" loops without variables q automatic memory management q 3

Functions finally get some respect! functions are first class entities in functional languages q

Functions finally get some respect! functions are first class entities in functional languages q a first class entity in a programming language is something that can be: n passed as argument to a subprogram n returned as result from a subprogram n used as an operand or r-value q ; Scheme example: apply function to all values in a list (define apply-to-all ( fun values ) (if (null? values) '() (cons (fun (car values) ) (apply-to-all fun (cdr values) ) ) ; recursion ) ) 4

Functions finally get some respect (2) we can use apply-to-all to evaluate any function

Functions finally get some respect (2) we can use apply-to-all to evaluate any function q arguments don't have to be numbers q ; even? is a builtin function that returns TRUE for even > (apply-to-all even? '(3 8 12 5 22) ) (#f #t #t #f #t) ; define our own square function, then use it (define (square x) (* x x) ) > > (apply-to-all square '(2 5 8 100 12345678) ) (4 25 64 10000 152415765279684) 5

Applications q Artificial intelligence q Expert systems n n q Program can "learn" by

Applications q Artificial intelligence q Expert systems n n q Program can "learn" by creating new functions Theory of computing n q these areas make use of ability to dynamically define functions. simulate functional nature of computation Prototyping n programs have no side-effects, so easy to isolate errors and built modular programs 6

Pure Functional Programming q Variables represent values, not memory locations, OK: define pi =

Pure Functional Programming q Variables represent values, not memory locations, OK: define pi = 3. 14159 Illegal: x = x + 1; q No loops (why? ) q No state 7

Referentially Transparent the value of a function depends only on the value of its

Referentially Transparent the value of a function depends only on the value of its parameters. q No state q Question: Which of these functions are referentially transparent? C: int c = getchar(); Java: int c = System. in. read(); Java: double y = Math. sqrt(7. 5); Java: double r = Math. random( ); 8

Notes and Examples q Any referentially transparent function with no parameters must always return

Notes and Examples q Any referentially transparent function with no parameters must always return the same value! n not referentially transparent: random( ) getchar( ) q sorting: cannot sort an array in place (no reassignment) n must create a new constant array of sorted values. 9

Replacing Loops with Recursion Mathematical functions use recursion for iterative def'n Factorial(n) : =

Replacing Loops with Recursion Mathematical functions use recursion for iterative def'n Factorial(n) : = n * Factorial(n - 1) for n > 0 q Functional programming uses recursion instead of loops q C example: q long factorial(long n) { int k; long result = 1; for(k = 1; k <= n; k++) result = k * result; return result; } q same function using recursion: Local variables not needed! long factorial(long n) { if (n <= 1) return 1; else return n * factorial(n-1); } 10

Tail Recursion q q Tail recursion means that the last operation in a control

Tail Recursion q q Tail recursion means that the last operation in a control flow is recursion. Tail recursion can be done efficiently by an interpreter or compiler. n old stack frame can be replaced with recursive call n unwinding of a deep stack is not necessary q LISP and Scheme require that interpreters optimize tail recursion q The factorial example is not tail recursion: long factorial(long n) { if (n <= 1) return 1; return n * factorial(n-1); } Must call factorial before multiplication can be done. 11

Tail Recursion (2) q To use tail recursion, perform the last multiplication recursively: //

Tail Recursion (2) q To use tail recursion, perform the last multiplication recursively: // "helper function" uses tail recursion long tailfact(int n, long result) { if (n <= 1) return result; return tailfact(n-1, result*n); } Tail call // main factorial function long factorial(int n) { return tailfail(n, 1 L); } 12

Factorial in Scheme w/ tail recursion (define (tailfact n result) ; syntax: (if (test-expr)

Factorial in Scheme w/ tail recursion (define (tailfact n result) ; syntax: (if (test-expr) expr 1 expr 2) (if (<= n 1) result (tailfact (- n 1) (* n result) ) (define (factorial n) (tailfact n 1) ) q Try this: (factorial 500) 13

Lambda expressions q q q A lambda expression defines a nameless function: l(x) x*x

Lambda expressions q q q A lambda expression defines a nameless function: l(x) x*x defines a nameless function that squares a value. Lambda calculus says nothing about operations like *, +, sqrt( ). It's just an expression. Lambda calculus is concerned only with functional operations such as: n reduction: (l(x) x*x) (5) is 5*5 n composition: f (l(x) x*x) g (l(y) y+5) f g(u) is (u+5)*(u+5) 14

Lambda expressions in Scheme q A lambda expression defines a nameless (lambda (x) (*

Lambda expressions in Scheme q A lambda expression defines a nameless (lambda (x) (* x x) ) apply this function just like any other Scheme function: > ( (lambda (x) (* x x) ) 7) 49 q The syntax of lambda expressions is (lambda list-of-parameters expr 1 expr 2 … ) q The Scheme interpreter tells you this is a function: > (lambda (x) (* x x) ) #<procedure> 15

define and lambda q Use lambda and define to create named functions: (define sqr

define and lambda q Use lambda and define to create named functions: (define sqr (lambda (x) (* x x)) ) (sqr 5) q ; returns 25 To reduce typing, Scheme defines a "function" form of define: (define (sqr x) (* x x) ) (define (name args) expression [. . . ] ) is syntactic sugar for (define name (lambda (args) expression [. . . ]) ) 16

Lambda examples q q Lambda is used to generate functions dynamically, usually as return

Lambda examples q q Lambda is used to generate functions dynamically, usually as return values from other functions This enables functions to be first class entities (define (scale-by f) ( lambda(x) (* x f) ) ) (define inch 2 cm (scale-by 2. 54) ) ; inches to cm (define lb 2 kg (scale-by 0. 4545) ) ; pound to kg ; now inch 2 cm and lb 2 kg are functions! > (inch 2 cm 10) 25. 4 > (lb 2 kg 50) 22. 725 17

Lambda calculus q q The lambda function comes from Lambda calculus: see textbook or

Lambda calculus q q The lambda function comes from Lambda calculus: see textbook or search the Internet. A parameter in a lambda expression is bound if it refers to one of the parameters of the lambda, otherwise it is free. (lambda (x) (* x y) ) q ; x is bound, y is free Consider a lambda that defines another function (define mult (lambda(y) (lambda(x) (* x y)) )) ; both x and y are bound. (define g (mult 5) ) ; g(x) = (* x 5) > (g 8) 40 18

Scheme: A Lisp dialect Simple syntax, similar to LISP. q Developed at MIT in

Scheme: A Lisp dialect Simple syntax, similar to LISP. q Developed at MIT in 1970 s. Used to teach programming. q Static scoping. q Functions as first-class entities. q Removes some odd behavior from Lisp. n but adds some incompatibilities. . . q (define a '()) > (if a (display "true") (display "false")) § In LISP, an empty list is "false". § In Scheme, any list (including empty one) is "true". 19

Scheme Syntax 20

Scheme Syntax 20

Scheme: A Lisp dialect q Basic syntax: expression atom | list '(' { expression

Scheme: A Lisp dialect q Basic syntax: expression atom | list '(' { expression } ')' atom number | string | identifier | character | boolean q Everything is an expression: programs, data, anything. q Lists are (almost) the only structure. q A program consists of expressions. 21

Scheme Expressions: examples a number a string Boolean value "true" false the character 'a'

Scheme Expressions: examples a number a string Boolean value "true" false the character 'a' an identifier another identifier a list of numbers list containing other lists list consisting of the identifier "+" (a built-in procedure) and two numbers ( (+ 2 3) (/ 6 2)) list consisting of an identifier and two lists 42 "hello" #t or #T #f or #F #a a hello (2. 1 2. 2 -3) (1 (2 3) (a) ) (+ 2 3) 22

Scheme Operation Programs are executed by evaluating expressions. q A Scheme program consists of

Scheme Operation Programs are executed by evaluating expressions. q A Scheme program consists of a series of expressions. q Usually, the expressions are define's. q Interpreter runs in “read-eval-print” loop. q Programs can explicitly use eval to evaluate expressions. q (define pi 3. 14159) (define (area-of-circle rad) (* pi rad) ) (area-of-circle 10) 23

Expression Evaluation Expression Value 10 10 3/5 0. 6 (fractional form OK) (+ a

Expression Evaluation Expression Value 10 10 3/5 0. 6 (fractional form OK) (+ a b c d e) sum of values: (+) = 0 (* a b c d) product of values: (*) = 1 (+ 3 4) 7 (* 3 4 5) 60 (+ (* 3 4) (* 5 6)) 42 (= 10 (* 2 5)) "10 = 2*5"? #t (true) (> 3 5 ) "3 > 5"? #f (false) (and (= a b) (<> a 0)) (a == b) && (a != 0) (not (= x 1) ) !(x==1) (read-char) input char, like C getchar() 24

Defining Values To define a symbol in Scheme, use “define”. (define pi 3. 14159)

Defining Values To define a symbol in Scheme, use “define”. (define pi 3. 14159) (define n 20) (define n-square (* n n ) ) 25

Defining Functions Syntax: (define (function_name parameters) expression { expression } ) the value of

Defining Functions Syntax: (define (function_name parameters) expression { expression } ) the value of the function is the value of the last expression. q Area of a rectangle: (define (area width height) (* width height) ) q Hypotenuse of a triangle: (define (hypo side 1 side 2) (sqrt (+ (* side 1) (* side 2) ) or: (define (hypo side 1 side 2) (sqrt (+ (square side 1) (square side 2) ) 26

Input and Output Functions Not available in beginner's level Dr. Scheme: (read) read space-delimited

Input and Output Functions Not available in beginner's level Dr. Scheme: (read) read space-delimited value (display expression ) output a value (newline) (display "Please input something: ") (define x (read) ) (display (cons "you input: " (list x))) Please input something: you input 4. 5 Please input something: you input hello 4. 5 hello 27

A Look at Dr. Scheme Language Choice Dialog Definitions area Interactions area 28

A Look at Dr. Scheme Language Choice Dialog Definitions area Interactions area 28

Dr. Scheme online help 29

Dr. Scheme online help 29

Context-sensitive help, syntax checker right-click for context menu syntax checker and easy-to-use debugging 30

Context-sensitive help, syntax checker right-click for context menu syntax checker and easy-to-use debugging 30

Numeric Predicate Functions These functions compare numeric values and return true (#t) or false

Numeric Predicate Functions These functions compare numeric values and return true (#t) or false (#f). q LISP (not Scheme) may return () for "false". q (= a b) (<> a b) (<= a b) (>= a b) (even? x) (odd? x) (zero? a) numeric equality, a == b (not (= a b) ) a>b a<b (or (< a b) (= a b) ) is x an even number? is x an odd number? (= a 0) 31

if function Syntax: (if predicate then_expression else_expression) "if" always has 3 expressions. (define (fabs

if function Syntax: (if predicate then_expression else_expression) "if" always has 3 expressions. (define (fabs x) (if (>= x 0) x (* -1 x) ) ) Note: Scheme has a built-in function named "abs". 32

Control Flow using Predicates (define (factorial n) (if (<= n 0) 1 (* n

Control Flow using Predicates (define (factorial n) (if (<= n 0) 1 (* n (factorial (- n 1) ) ) q Scheme performs calculations using arbitrary precision: (factorial 100) 93326215443944152681699238856266700490715968264 31621468592963895217599993229915608941463976156 5182862536979208272237582511852109168640000000 33

cond function true or false (cond (predicate 1 expression { expression }) (predicate 2

cond function true or false (cond (predicate 1 expression { expression }) (predicate 2 expression { expression }) (predicate 3 expression { expression }). . . (else expression { expression } ) ) q q Each of the predicates is evaluated (in order) until a predicate evaluates to True. Then, all expressions for that predicate are evaluated and the value of the last expression is the return value of cond. If no predicates are true, then the "else" clause is used and the value of the last expression is returned. 34

cond example q define a function f(x) that returns: (define (cond ( ( (

cond example q define a function f(x) that returns: (define (cond ( ( ( ) ) (f x) (< x 0) 0 ) (<= x 1) (* x (sqrt x) ) ) else (* x x) ) 35

if and compared q q if contains one predicate and 2 cases ("then" and

if and compared q q if contains one predicate and 2 cases ("then" and "else"). cond contains an arbitrary number of predicates, evaluated conditionally. q cond is similar to "if. . else if. . . else. . . " in C or Java. q cond clauses may contain any number of expressions. q In Dr. Scheme "student" level, each clause can contain only one predicate ("question") and one other expression ("answer"). Q: Can you replace "cond" with a series of "if" statements? 36

cond replaced by "if" q define a function f(x) that returns: (define (ff x)

cond replaced by "if" q define a function f(x) that returns: (define (ff x) (if (< x 0) 0 ( if (<= x 1) (* x (sqrt x) ) (* x x) ) 37

Type Predicate Functions q test the type of an argument and return #t or

Type Predicate Functions q test the type of an argument and return #t or #f (boolean? x) is x a boolean? (char? x) is x a character? (list? x) is x a list? (number? x) is x a number? (int or floating point) (pair? x) is x a pair? (has car and cdr) (string? x) is x a string? (symbol? x) is x a valid symbol? (symbol? '$x-%y) #t ($x-%y is a valid symbol) (list? 5) #f 38

List Functions: quote and list quote or ' prevents evaluation of a list q

List Functions: quote and list quote or ' prevents evaluation of a list q quote is used to create data constants q Why is this needed? (quote a) a (quote (a b c)) (a b c) '(a b c) (quote (a b c)) q list makes a list of its arguments (list 'a) (a) (list '(a b) '(c d)) ((a b) (c d)) (list (* 5 2) (/ 6 2)) (10 3) 39

Breaking down a list: car cdr essential list manipulation functions in Scheme q car

Breaking down a list: car cdr essential list manipulation functions in Scheme q car returns the first element from a list q q cdr returns everything after the first element of a list q the argument must be a non-empty list (car '(a b c)) a (cdr '(a b c)) (b c) (car '((a b) c)) (a b) (cdr '((a b) c)) (c) (car '(a) ) a (cdr '(a) ) () (car '() ) error (empty list) (cdr 'a ) error (argument not a list) 40

Building a list: cons q q prepend a value to list, and return as

Building a list: cons q q prepend a value to list, and return as a new list: (cons expression list) the second argument should be a list (cons 'a '(b c)) (a b c) (cons '(a) '(b c)) ((a) b c) (cons '(a b) '(c d)) ((a b) c d) (cons '() '(b c) ) (() b c) (cons 'a 'b ) (a. b) the last example is called a "dotted pair" and is usually an error. q (a. b) means that a list element contains two atoms instead of an atom (or pointer) and a pointer q 41

Building a list: list & append q q append several lists to create a

Building a list: list & append q q append several lists to create a single list: (append list 1 list 2. . . ) the arguments should be lists (append '(a b) '(c d)) (a b c d) (cons '(a b) '(c d)) ((a b) c d) (list '(a b) '(c d)) ((a b) (c d)) (append '(a) '(b c) '(d)) (a b c d) (append '(a b) '(d)) (a b d) (append '(a b) 'c ) error: 'c is not a list append, cons, and list are essential for building lists: you should understand them!! 42

Why "car" and "cdr"? The names CAR and CDR come from LISP, which was

Why "car" and "cdr"? The names CAR and CDR come from LISP, which was first implemented on an IBM 704 computer. q IBM 704 words had two fields: address and decrement, that could each store a memory address. q LISP used these 2 fields to store the 2 elements of each node in a list (value and pointer to next node). q list a address decre. register b 43

Why "car" and "cdr"? The 704 had two machine instructions to access these values:

Why "car" and "cdr"? The 704 had two machine instructions to access these values: Contents of Address Register (CAR) Contents of Decrement Register (CDR) hence the name of the LISP commands!. . . and LISP is supposedly "machine independent". . . HA! (car list) a (cdr list) b 44

Why "car" and "cdr"? How to store a list: List = ( a (b

Why "car" and "cdr"? How to store a list: List = ( a (b c) d ) a List d b c address decre. register car(List)= a cdr(List) d b c 45

Compound car and cdr are often used several times in succession: (car (cdr List)

Compound car and cdr are often used several times in succession: (car (cdr List) ) = get 2 nd element of List (cdr List) ) = delete first 2 items from List so, Scheme defines several compound car/cdr functions: car (caar List ) (caddr List ) (cddddr List ) (cdadadr List ) (cxxxxxr List ) = (car List) ) = (car (cdr List) ) ) = (cdr List) ) = (cdr (car (cdr List) ) ) = any combination of up to 5 "a" and "d" refers to a composite of car and cdr 46

Tests (list? expression) true if expression is a list (null? expression) true if expression

Tests (list? expression) true if expression is a list (null? expression) true if expression is a null list (eq? ex 1 ex 2) true if ex 1 and ex 2 are both atoms and identical (list? '(x y) ) (list? 'x) (list? '()) (null? '(a b) ) (null? '() ) (null? 'A) (eq? 'a 'a) (eq? 'a '(a)) (eq? '(a b)) #T #F or ( ) #T or #F (implementation dependent) 47

List Processing: cdr down & cons up Many functions operate on a list and

List Processing: cdr down & cons up Many functions operate on a list and produce a new list as a result. 1. operate on the first element: (car List) 2. recursive call for rest of the list: (fun (cdr List) ) 3. put the results together (cons first-result recursive-result ) cdr down the list ; square each element of a list (define (square-all L) termination condition (if (null? L) '() (cons (* (car L)) (square-all (cdr L))) )) cons join results together 48

List Manipulation: cdr down & cons up "cdr down and cons up" is a

List Manipulation: cdr down & cons up "cdr down and cons up" is a common technique for applying operations to all elements of a list. ; append two lists (define (append L M) cdr down the list (if (null? L) M (cons (car L) (append (cdr L) M))) ) cons up the result ; reverse a list (define (reverse L) (if (null? L) '( ) (append (reverse (cdr L)) (list (car L))) ) ) create a list from element 49

returns false, #F St ud (member 'B '(A (B C) D)) oo k (member

returns false, #F St ud (member 'B '(A (B C) D)) oo k (member 'B '(A C D)) ex tb returns true, #T yt (member 'B '(A B C)) ex am Write a "member" function that returns true if the first argument is a member of the second arg (a list): pl e Textbook example: member (define (member atm lis) (cond ((null? lis) #F ) ((eq? atm (car lis)) #T) ; compare first elem (else (member atm (cdr lis))) ; compare rest ) ) 50

member built-in function Scheme has a member function. It returns the tail of the

member built-in function Scheme has a member function. It returns the tail of the list beginning with the search element. (member 'B '(A B C)) returns (B C) (member 'B '(A C D)) returns #F (member '(B) '(A ((B) D))) returns ((B) D) 51

Scoping q Scheme uses static scope. q "let" creates a new scope: (define a

Scoping q Scheme uses static scope. q "let" creates a new scope: (define a 10) (define (f x ) (let (a 10) # create a new a (* a x) ) ) 52

Filter Function q A more interesting example: define a filter for lists. > (filter

Filter Function q A more interesting example: define a filter for lists. > (filter odd? '(2 3 4 5 6 7 8) ) (3 5 7) ; extract elements from List that satisfy f (define (filter f List) (cond ( (null? List) '() ) ( (f (car List)) ; filter function is true (cons (car List) (filter f (cdr List))) ) ( else (filter f (cdr List)) ) 53

filter example (1) (filter even? '(1 2 4 7) ) (cond ( (null? '(1

filter example (1) (filter even? '(1 2 4 7) ) (cond ( (null? '(1 2 4 7). . . ) #F ( (even? 1). . . ) #F ( else (filter even? '(2 4 7) ) ) #T (filter even? '(2 4 7) ) (cond ( (null? '(2 4 7). . . ) #F ( (even? 2) (cons 2 (filter even? '(4 7)) ) #T ) (filter even? '(4 7) ) (cond ( (null? '(4 7). . . ) #F ( (even? 4) (cons 4 (filter even? '(7)) ) #T ) (filter even? '(7) ) 54

filter example (2) (filter even? '(7) ) (cond. . . (else (filter even? '()

filter example (2) (filter even? '(7) ) (cond. . . (else (filter even? '() ) ) returns: '( ) (filter even? '(4 7) ) (cond. . . ( (even? 4) (cons 4 (filter even? '(7)) ) #T returns: (cons 4 '()) => '(4) (filter even? '(2 4 7) ) (cond. . . ( (even? 2) (cons 2 (filter even? '(4 7)) ) #T returns: (cons 2 '(4)) => '(2 4) (filter even? '(1 2 4 7) ) (cond. . . ( else (filter even? '(2 4 7) ) ) #T returns: '(2 4) 55

Boolean and Numeric Functions Boolean Functions (not expression)logical negation (and expr 1 expr 2)

Boolean and Numeric Functions Boolean Functions (not expression)logical negation (and expr 1 expr 2) logical and (or expr 1 expr 2)logical or q Numeric Functions (sqrt a) returns (a)1/2 (sqr a) returns a 2 (expt A B) returns AB (remainder A B) remainder of integer division A/B (log A) natural logarithm of A (sin A), (cos A), . . . trigonometric functions, A is in radians (max a b c d. . . ) max of several values (min a b c d. . . ) min of several values (random n) returns a random integer value 0, 1, . . . , n-1 q 56

String Functions (string-length "hello") number of characters in string (substring start end ) return

String Functions (string-length "hello") number of characters in string (substring start end ) return a substring (string->list "hello there" ) convert to list of characters (list->string (#h #i) ) convert list of chars to a string (string #h #e #l #o ) concatenate char args to new string (string-copy string ) create a new string as copy of old (string? arg ) true if argument is a string (string=? string 1. . . ) there also < > <= >= functions (string=? "bye" "BYE" ) false (string-ci=? "bye" "BYE" ) true. there also < > <= >= (string-null? string ) (string-index string char ) (string-rindex string char ) 57

#C#h#a#r#a#c#t#e#r Functions char? obj true of obj is a character char=? char. . .

#C#h#a#r#a#c#t#e#r Functions char? obj true of obj is a character char=? char. . . equals comparison. also < <= > >= char-ci=? char. . . case insensitive =. also < <= > >= (char=? #A #a ) false (char-ci=? #A #a ) true char-alphabetic? char true if alphabetic character char-numeric? char true if numeric character char-whitespace? char true if whitespace char-upper-case? char-lower-case? char->integer char to int, (char->integer #a) is 50 integer->char integer char sequence num. to char-upcase char-downcase char 58

Special String and Char Values String � f n r t a v Character

Special String and Char Values String f n r t a v Character #null #ack #newline #return #tab #bel #vt C/Java Equivalent or null f n r t a v > (display "hellotdogn woof!") hello dog woof! 59

Code blocks using ( begin. . . ) begin is used to insert several

Code blocks using ( begin. . . ) begin is used to insert several expressions where a Scheme command expects one, like Pascal begin. . . end. syntax: (begin (expression 1) (expression 2). . . ) (* Pascal *) if (x < 0) then begin statement; . . . end else begin statement; . . . end; ; Scheme (if (< x 0) ( begin expression. . . ) ( begin ; else part expression. . . ) ) ; end of "(if. . . " 60

Testing Equality in Scheme has many different equality functions: q = applies only to

Testing Equality in Scheme has many different equality functions: q = applies only to numbers: (= x y) q char=? applies only to characters: (char=? #a #b) q string=? applies only to strings q Each non-numeric data type has its own equality function. 61

General Equality Functions There are three “generic” equality functions: (eq? a b) test if

General Equality Functions There are three “generic” equality functions: (eq? a b) test if a and b refer to same object, like == in Java (eqv? a b) test if a and b are equivalent (equal? a b) test atom-by-atom equality of lists. like obj. equals( ) in Java. > (define > (eq? L 1 false > (equal? true L 1 '(a b c) ) L 2) L 1 L 2) 62

Scheme evaluation rules 1. Constant atoms, such as numbers and strings, evaluate to themselves:

Scheme evaluation rules 1. Constant atoms, such as numbers and strings, evaluate to themselves: 4. 2, "hello" 2. Identifiers are looked up in the current environment and replaced by the value found there. 3. A list is evaluated by recursively evaluating each element in the list (in an unspecified order). 4. The first expression in the list must evaluate to a function. This function is applied to the remaining values in the list. Thus, all expressions are in prefix form. 63

Example: Equals (1) Write an "Equals" function that returns true if two lists are

Example: Equals (1) Write an "Equals" function that returns true if two lists are equal: (Equals '(B C) ) returns true (Equals '(B C) '(B C D) ) returns false (define (Equals L 1 L 2) (cond ( (null? L 1) (null? L 2) ) ( (null? L 2) #F ) ( (eq? (car L 1) (car L 2)) (Equals (cdr L 1) (cdr L 2) ) ) ( else #F ) ) ) 64

Example: Equals (2) Equals (1) doesn't work if the arguments are atoms (Equals 'a

Example: Equals (2) Equals (1) doesn't work if the arguments are atoms (Equals 'a 'a ) Error (define (Equals L 1 L 2) (cond ( (not (list? L 1)) (eq? L 1 L 2) ) ( (not (list? L 2)) #F ) ( (null? L 1) (null? L 2) ) ( (null? L 2) #F ) ( (eq? (car L 1)(car L 2)) (Equals (cdr L 1) (cdr L 2) ) ) ( else #F ) ) ) 65

Example: Equals (3) Equals (2) doesn't work if the list contains other lists (Equals

Example: Equals (3) Equals (2) doesn't work if the list contains other lists (Equals '((a b) c) ) Fix this using more recursion. . . (define (Equals L 1 L 2) (cond ( (not (list? L 1)) (eq? L 1 L 2) ) ( (not (list? L 2)) '() ) ( (null? L 1) (null? L 2) ) ( (null? L 2) '() ) ( (Equals (car L 1) (car L 2)) (Equals (cdr L 1) (cdr L 2) ) ) ( else '() ) 66

More Examples The boring GCD function: (define (gcd u v) ; gcd of u

More Examples The boring GCD function: (define (gcd u v) ; gcd of u and v (if (= v 0) u (gcd v (remainder u v)) ) ) A "power" function to compute xn, for integer n. (define (power (cond ((< n 0) ((= n 0) (else (* ) ) x n) (/ 1 (power x (- 0 n)))) ; 1/x^(-n) 1 ) ; x^0 = 1 x (power x (- n 1)))) 67

for-each Syntax: (for-each function list 1 [list 2. . . ] ) function is

for-each Syntax: (for-each function list 1 [list 2. . . ] ) function is called repeatedly; on the k-th call it is given the k-th element from list 1, list 2, . . . The lists (list 1 list 2. . . ) must have the same lengths. > (for-each * '(3 4 > > (for-each (lambda (display (* '(3 4 5) '(5 2 15 8 100 5) '(5 2 20) ) ; nothing returned (a b) a b )) (newline)) 20)) ; 3*5 ; 4*2 ; 5*20 68

Evaluating Expressions: eval q The Scheme interpreter "executes" your program by invoking the eval

Evaluating Expressions: eval q The Scheme interpreter "executes" your program by invoking the eval function. q The interpreter is said to run a "read - eval - print" loop. q You can use eval in your code, too. Usage ( eval list ) > (define hi '( display "hello" ) ) > > (eval hi ) Hello 69

How to. . . q How would you use eval to create a "sum"

How to. . . q How would you use eval to create a "sum" function: Usage ( sum list-of-numbers ) > ( sum '( 1 2 3 4 5 ) ) 15 This won't work: (+ list-of-numbers ) What we want is: '+ ( 1 2 3 4 5 ) 70

Evaluating Expressions: eval Example: Sum the elements in a list > (define data '(

Evaluating Expressions: eval Example: Sum the elements in a list > (define data '( 12 3 7 99 23 17 88 ) ) > (cons '+ data ) ( + 12 3 7 99 23 17 88 ) > (eval (cons '+ data ) ) 249 71

Exercise using eval Exercise: 1. Define a "sum" function that sums a list: (sum

Exercise using eval Exercise: 1. Define a "sum" function that sums a list: (sum list) 2. Define a "square" function: (square x) is x^2 3. Define an average function that computes the average of a list of numbers. Use length. 4. Define a variance function that computes the variance of a list of numbers. The variance can be computed as: variance = (average data^2) - (average data)^2 Ex: (variance '(0 1) ) is 1/4 (variance '(20 20 20)) is 0 72

Use of eval enables your program to write its own instructions and then run

Use of eval enables your program to write its own instructions and then run them! q eval q this is another way to create programs that learn. In comparison: n lambda n eval returns a new, unnamed function evaluates a list. 73

Applicative Order Evaluation q q Applicative (aka eager) order evaluation: arguments are evaluated at

Applicative Order Evaluation q q Applicative (aka eager) order evaluation: arguments are evaluated at the call location (caller) before they are passed to the called function. Example: (* (sin x) (/ x 2) ) compute sin(x) and (x/2) first, then call * to multiply Applicative evaluation is used in most languages, including C, Java, Pascal, and Scheme. . . with exceptions. Q: In what situations might applicative order evaluation be a problem? 74

Delayed Evaluation Consider the use of "if" in C: if ( x > 0

Delayed Evaluation Consider the use of "if" in C: if ( x > 0 ) y = log(x); else printf("x must be positive"); n n q q is only evaluated if (x>0) is true printf(. . . ) is only evaluated if (x>0) is false y = log(x) This is an example of delayed evaluation: n delayed evaluation is an essential part of "if" n then part is only evaluated if test condition is true. Also called normal order evaluation 75

Delayed Evaluation (2) q Consider "if" and "and" in Scheme: (if (> x 0)

Delayed Evaluation (2) q Consider "if" and "and" in Scheme: (if (> x 0) (log x) (display "x must be pos") ) if applicative order evaluation is used here, then all three expressions would be evaluated before the "if" function is called! Result: q would always be computed n (log x) n (display ". . . ") would always be executed (if a b c) must use delayed evaluation. 76

Lazy Evaluation q An expression is evaluated the first time it is needed. q

Lazy Evaluation q An expression is evaluated the first time it is needed. q It is not evaluated again. q This is not the same as "normal order" evaluation. 77

Short-circuit Evaluation in C and Java q The && and || operators use short-circuit

Short-circuit Evaluation in C and Java q The && and || operators use short-circuit evaluation: if ( x != 0 && y/x < 1 ). . . ; n y/x is only evaluated if (x != 0) is true if ( x == 0 || log(x) < 1 ). . . ; n q log(x) is only evaluated if (x == 0) is false C, C#, and Java guarantee this property of && and || 78

Short-circuit Evaluation in Scheme q What about "and" in Scheme? (if (and (f x)

Short-circuit Evaluation in Scheme q What about "and" in Scheme? (if (and (f x) (g x)) (display "True") ; ; then statement (display "False") ; ; else statement ) does Scheme always evaluate (g x) ? q Write a test program: (define (f x) (display "F called") #f ) (define (g x) (display "G called") #t ) evaluate: (and (f 1) (g 1) ) (and (g 1) (f 1) ) (or (f 1) (g 1) ) (or (g 1) (f 1) ) 79

Delayed Evaluation (3) Other situations where delayed evaluation is needed: q cond (condition 1

Delayed Evaluation (3) Other situations where delayed evaluation is needed: q cond (condition 1 expression 1) (condition 2 expression 2). . . (else expression 3) ) evaluation of arguments is delayed until they are needed by "cond". q Producer - consumer relationship (described next). 80

Delayed Evaluation (4) q Applications can also benefit from delayed evaluation: ; generate a

Delayed Evaluation (4) q Applications can also benefit from delayed evaluation: ; generate a list of integers from m to n (define (intlist m n) (if (> m n) '() (cons m (intlist (+ 1 m) n)) ) ) ; extract first n items from list (define (head n List) (if (= n 0) '() (cons (car List)(head (- n 1)(cdr List))) ) ) ; extract first 10 items from list of integers (head 10 (intlist 1 100000) ) 81

Delayed Evaluation (5) q intlist is evaluated first, but only the first 10 items

Delayed Evaluation (5) q intlist is evaluated first, but only the first 10 items are used, so the rest of the work was unnecessary. ; extract first 10 items from list (head 10 (intlist 1 100000) ) 82

delay and force q q q delay requests that an expression be evaluated later.

delay and force q q q delay requests that an expression be evaluated later. Scheme creates a "promise" to evaluate it at a later time: (delay (+ 3 4)) #<struct: promise> force causes the "promise" to be fulfilled. The expression is evaluated and the result returned. The promise is not turned into a value -- it stays a promise. > (define E (delay (+ 3 4))) > E #<struct: promise> > (force E) E is still a promise, not a value 7 > (* E 2) ; multiply E by 2 *: expects type <number> as 1 st argument, given: #<struct: promise> 83

Uses of delay avoid a long calculation that may not be necessary q to

Uses of delay avoid a long calculation that may not be necessary q to enable a function to generate an infinite amount of data n each time the caller wants the next term he forces the tail of the function. n this causes the calculation to perform one increment q ; ; generate all the integers starting from n (define (integers n) (cons n (integers (+ n 1) ) This recursion will never stop! 84

Applying delay and force q Rewrite integers to use delay : ; generate a

Applying delay and force q Rewrite integers to use delay : ; generate a list of all integers starting at n (define (integers n) (cons n (delay (integers (+ 1 n)) ) ; extract first n items from list (define (head n list) (if (= n 0) '() (cons (car (force list)) (head (- n 1)(cdr (force list)))) ) ) ; example usage: (head 100 (delay (integers 1) ) ) 85

Applying delay and force (2) q Each reference to the list generator is wrapped

Applying delay and force (2) q Each reference to the list generator is wrapped in (delay. . . ) or (force. . . ) ; generate a list of all integers (define (integers n) (cons n (delay (integers (+ 1 n)) ) ; consume first n items from list (define (head n list) (if (= n 0) '() (cons (car (force list)) (head (- n 1)(cdr (force list)))) ) ) The generator delays building the list; The consumer forces each next step of list building. 86

Is this inefficient? "head" (list consumer) forces the list 2 times. q Does that

Is this inefficient? "head" (list consumer) forces the list 2 times. q Does that cause the generator to do the work twice? q ; generate a list of all integers (define (integers n) (cons n (delay (integers (+ 1 n)) ) ; consume first n items from list (define (head n list) (if (= n 0) '() (cons (car (force list)) (head (- n 1)(cdr (force list)))) ) ) 87

Memoization q Promises would be inefficient if they are evaluated every time a delayed

Memoization q Promises would be inefficient if they are evaluated every time a delayed expression is forced: (define E (delay (+ 1 2 3 4 5 6 7 8 9 10)) (define (f-square x) (* (force x))) q q q (f-square E) would require the sum to be computed twice. To avoid this, promises are memo-ized: n when a promise is force-d, the value is stored n subsequent "force" simply return the stored value Thus, a delay expression is evaluated at most once. 88

Memoization Exposed q Memoization can be seen in Scheme using a definition that involves

Memoization Exposed q Memoization can be seen in Scheme using a definition that involves I/O: (define Say. Hello (delay (display "Hello There"))) > Say. Hello # <struct: promise> > (force Say. Hello) Hello There > (force Say. Hello) > No output from the second "force". 89

Functions as 1 st class entities q Result of a lambda can be manipulated

Functions as 1 st class entities q Result of a lambda can be manipulated as ordinary data: > ( define f (lambda (x) (* x x)) ) > f (#<procedure>) > (f 5) 25 (define (scale-by f) ( lambda(x) (* x f) ) ) (define inch 2 cm (scale-by 2. 54) ) ; inches to cm (inch 2 cm 20 ) ; use the func. 50. 8 90

Higher-order functions q q q A higher-order function returns a function as its value,

Higher-order functions q q q A higher-order function returns a function as its value, or takes a function as a parameter. eval and map are higher-order The use of higher-order functions is a characteristic of functional programs 91

Higher-order functions ; apply function to all values in a list (define apply-to-all (

Higher-order functions ; apply function to all values in a list (define apply-to-all ( fun values ) (if (null? values) '() (cons (fun (car values) ) (apply-to-all fun (cdr values) ) ) ; recursion ) ) The Scheme map function performs apply-to-all. Example: ; ; compute factorial of all values in a list > (map factorial '(1 2 3 4 5 6) ) (1 2 6 24 120 720) 92

Higher-order functions ; apply a filter (p) to elements of a list L (define

Higher-order functions ; apply a filter (p) to elements of a list L (define (filter p L) (cond ( (null? L) L ) ( (p (car L)) (cons (car L) (filter p (cdr L))) ) ( else (filter p (cdr L)) ) Example: > (filter even? '(1 2 4 7) ) see next slide for step-by-step evaluation. 93

power function generator q Define a square function and a cube function: (define (square

power function generator q Define a square function and a cube function: (define (square x) (* x x) ) (define (cube x) (* x x x) ) > (square 3) 9 > (cube 3) 27 q Can we define a function that can generate any power function? (for integer powers) That is: (define square (power 2) ) ; square is a function (define cube (power 3) ) ; cube is a function (define inverse (power -1) ) 94

power function generator (cont'd) (define (power n) (cond ; n = 0 is a

power function generator (cont'd) (define (power n) (cond ; n = 0 is a constant function: x^0 = 1 ( (= n 0) (lambda(x) 1 ) ) ; n = 1 is the identity function ( (= n 1) (lambda(x) x ) ) ; n < 0 use the property: x^n = 1/x^(n) ( (< n 0) (lambda(x) (/ 1 ((power (- 0 n)) x) ) ; n > 1 define recursively: x^n = x*x^(n-1) ( else (lambda(x). . . complete this as an 95

Organization of Lists in Scheme Lists are stored as. . . linked lists. q

Organization of Lists in Scheme Lists are stored as. . . linked lists. q The "car" of each node contains a type identifier (number, string, list) and pointer to value. Example: L = ( (1 2) 3 (4 (5 6) ) ) q 96

Question: alternative to car and cdr q In Scheme: = a = first element

Question: alternative to car and cdr q In Scheme: = a = first element (cdr '(a b c d e. . . ) ) = '(b c d e) = remainder (car '(a b c d e. . . ) ) q What would be the effect of replacing car and cdr with a "head" and "tail" like this: (head '(a b c. . . m n) ) = '(a b c. . . m) (tail '(a b c. . . m n) ) = n q = last element For a linked list structure, is one more efficient? car-cdr or head-tail 97

Question: alternative to car and cdr Consider: List = ( a (b c) d

Question: alternative to car and cdr Consider: List = ( a (b c) d ) car(List) = a cdr(List) = ( (b c) d List car(List) cdr(List) a b c car and cdr don't need to copy the list. 98

Question: alternative to car and cdr Consider: List = ( a (b c) d

Question: alternative to car and cdr Consider: List = ( a (b c) d ) head(List) = ( a (b c) ) tail(List) = d tail(List) d List a b c head(List) = ? 99

Data structures in Scheme has a set of cludgy commands for managing data structures.

Data structures in Scheme has a set of cludgy commands for managing data structures. q define-struct defines a new structure (define-struct person '(name telephone)) q make-structname creates a new instance (define shin (make-person "Taksin" '01 -5551212)) q struct-attribute commands are accessors: > (person-name shin) "Taksin" > (person-telephone shin) 01 -5551212 q make-person, person-name, . . . are defined automatically when you use "define-struct" 100

Object-oriented programming q Since functions are first class objects, an element of a structure

Object-oriented programming q Since functions are first class objects, an element of a structure can be a function. 101

Binary search trees q q q Represent each node as a 3 -item list:

Binary search trees q q q Represent each node as a 3 -item list: (data left-child right-child) '( mydata (left-child-list) (right-child-list) ) (define (data B) (car B)) (define (leftchild B) (cadr B)) (define (rightchild B) (caddr B)) Example - see Figure 11. 8, page 487: ("horse"("cow"()("dog"()())) ("zebra"("yak"()())())) Now we can write traversals such as (define (tree-to-list B) (if (null? B) B (append (tree-to-list (leftchild B)) (list (data B)) (tree-to-list (rightchild B))))) 102

eval and symbols q q q The eval function evaluates an expression in an

eval and symbols q q q The eval function evaluates an expression in an environment; many Scheme versions have an implied current environment: (eval (cons max '(1 3 2)) => 3 Symbols are virtually unique to Lisp: they are runtime variable names, or unevaluated identifiers: 'x => x (eval 'x) => the value of x in the environment Use symbols for enums (they are more efficient than strings) 103

Functions and objects q q Functions can be used to model objects and classes

Functions and objects q q Functions can be used to model objects and classes in Scheme. Consider the simple Java class: public class Bank. Account { public Bank. Account(double initial. Balance) { balance = initial. Balance; } public void deposit(double amount) { balance = balance + amount; } public void withdraw(double amount) { balance = balance - amount; } public double get. Balance() { return balance; } private double balance; } 104

Functions and objects (cont’d) q This can be modeled in Scheme as: (define (Bank.

Functions and objects (cont’d) q This can be modeled in Scheme as: (define (Bank. Account balance) (define (get. Balance) balance) (define (deposit amt) (set! balance (+ balance amt))) (define (withdraw amt) (set! balance (- balance amt))) (lambda (message) (cond ((eq? message 'get. Balance) ((eq? message 'deposit) ((eq? message 'withdraw) (else (error "unknown message" message))) ) ) 105

Functions and objects (cont’d) q This code can be used as follows: > (define

Functions and objects (cont’d) q This code can be used as follows: > (define > ((acct 1 50 > ((acct 2 100 > ((acct 1 > ((acct 2 > ((acct 1 10 > ((acct 2 150 > ((acct 1. unknown acct 1 (Bank. Account 50)) acct 2 (Bank. Account 100)) 'getbalance)) 'withdraw) 40) 'deposit) 50) 'getbalance)) 'setbalance) 100) message setbalance 106

Imperative Commands in Scheme q In the Bank. Account code set! enables us to

Imperative Commands in Scheme q In the Bank. Account code set! enables us to treat a symbol as a memory location and alter its value. set! is not purely functional programming: (set! balance (+ balance amount) ) q In Scheme, any function ending in “!” is a non-functional, imperative-style operation. These include: set! set-car! set-cdr! string-set! etc. All of these are versions of assignment. 107