1 / 107

Functional Programming with Scheme

Functional Programming with Scheme. Introduction to Functional Programming Concepts and the Scheme language. Introduction. In Theory of Computing , a program is viewed as a function. A program maps each input to some output: P: Input  Output

Télécharger la présentation

Functional Programming with Scheme

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Introduction • In Theory of Computing, a program is viewed as a function. A program maps each input to some output: P: Input  Output • deterministic program: the input completely determines the output: output = P(input) • 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 ... ) • Evaluating the program produces the output.

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

  4. Functions finally get some respect! • functions are first class entities in functional languages • a first class entity in a programming language is something that can be: • passed as argument to a subprogram • returned as result from a subprogram • used as an operand or r-value ; 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-allfun (cdr values) ) ) ; recursion ) )

  5. Functions finally get some respect (2) • we can use apply-to-all to evaluate any function • arguments don't have to be numbers ; 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)

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

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

  8. Referentially Transparent • the value of a function depends only on the value of its parameters. • No state 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( );

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

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

  11. Tail Recursion • Tail recursion means that the last operation in a control flow is recursion. • Tail recursion can be done efficiently by an interpreter or compiler. • old stack frame can be replaced with recursive call • unwinding of a deep stack is not necessary • LISP and Scheme require that interpreters optimize tail recursion • 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.

  12. Tail Recursion (2) • 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); } // main factorial function long factorial(int n) { return tailfail(n, 1L); } Tail call

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

  14. Lambda expressions • 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: • reduction: (l(x) x*x) (5) is 5*5 • composition: f(l(x) x*x) g(l(y) y+5) f g(u) is(u+5)*(u+5)

  15. Lambda expressions in Scheme • 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 • The syntax of lambda expressions is (lambdalist-of-parameters expr1 expr2 … ) • The Scheme interpreter tells you this is a function: > (lambda (x) (* x x) ) #<procedure>

  16. define and lambda • Use lambda and define to create named functions: (define sqr (lambda (x) (* x x)) ) (sqr 5) ; 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 [...]) )

  17. Lambda examples • Lambda is used to generate functions dynamically, usually as return values from other functions • This enables functions to befirst class entities (define (scale-by f) ( lambda(x) (* x f) ) ) (define inch2cm (scale-by 2.54) ) ; inches to cm (define lb2kg (scale-by 0.4545) ) ; pound to kg ; now inch2cm and lb2kg are functions! > (inch2cm 10) 25.4 > (lb2kg 50) 22.725

  18. Lambda calculus • 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) ) ; 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

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

  20. Scheme Syntax

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

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

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

  24. 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()

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

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

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

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

  29. Dr.Scheme online help

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

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

  32. if function Syntax: (ifpredicatethen_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".

  33. Control Flow using Predicates • Scheme performs calculations using arbitrary precision: (factorial 100) 933262154439441526816992388562667004907159682643162146859296389521759999322991560894146397615651828625369792082722375825118521091686400000000000000000000000 (define (factorial n) (if (<= n 0) 1 (* n (factorial (- n 1) ) ) ) )

  34. cond function true or false (cond (predicate1 expression { expression }) (predicate2 expression { expression }) (predicate3 expression { expression }) ... (else expression { expression } ) ) • 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.

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

  36. if and cond compared • if contains one predicate and 2 cases ("then" and "else"). • cond contains an arbitrary number of predicates, evaluated conditionally. • cond is similar to "if .. else if ... else if ... else ..." in C or Java. • cond clauses may contain any number of expressions. • 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?

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

  38. Type Predicate Functions • 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

  39. List Functions: quote and list • quote or ' prevents evaluation of a list • quote is used to create data constants Why is this needed? (quote a)a (quote (a b c))(a b c) '(a b c)(quote (a b c)) • 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)

  40. Breaking down a list: car cdr • essential list manipulation functions in Scheme • car returns the first element from a list • cdr returns everything after the first element of a list • 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)

  41. Building a list: cons • prepend a value to list, and return as a new list: (cons expressionlist) • 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. • (a . b) means that a list element contains two atoms instead of an atom (or pointer) and a pointer

  42. Building a list: list & append • append several lists to create a single list: (append list1list2 ...) • 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!!

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

  44. 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

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

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

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

  48. 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-resultrecursive-result ) cdr down the list ; square each element of a list (define (square-all L) (if (null? L) '() (cons (* (car L)(car L)) (square-all (cdr L))) )) termination condition cons join results together

  49. cons up the result 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) (if (null? L) M (cons (car L) (append (cdr L) M))) ) ; reverse a list (define (reverse L) (if (null? L) '( ) (append (reverse (cdr L)) (list (car L))) ) ) cdr down the list create a list from element

  50. Textbook example: member Write a "member" function that returns true if the first argument is a member of the second arg (a list): (member 'B '(A B C)) returns true, #T (member 'B '(A C D)) returns false, #F (member 'B '(A (B C) D)) returns false, #F Study textbook example (define (member atm lis) (cond ((null? lis) #F ) ((eq? atm (car lis)) #T) ; compare first elem (else (member atm (cdr lis))) ; compare rest ) )

More Related