Outline Introduction to functional programming Scheme: an untyped functional programming language
Storage vs. Value In imperative languages, stroage is visible: variables are names of storage cells. assignment changes the value in a storage cell. explicit allocation and deallocation of storage. computation is a sequence of updates to storage. Functional languages manipulates values, rather than storage. There is no notion of storage in functional languages. variables are names of values.
Assignment vs. Expression In pure functional programming, there is no assignment and each program (or function) is an expression. (define gcd (lambda (u v) (if (= v 0) u (gcd v (remainder u v)) ) ) ) v == 0 ? u : gcd(v, u % v);
Referential Transparency Due to the lack of assignment, the value of a function call depends only on the values of its arguments. gcd(9, 15) There is no explicit notion of state. This property makes the semantics of functional programs particularly simple.
Loops vs. Recursion Due to the lack of assignment, repetition cannot be carried out through loops. A loop must have a control variable that is reassigned as the loop executes. Repetition is carried out through recursion in functional languages.
Functions as Values In functional languages, functions are viewed as values. They can be manipulated in arbitrary ways without arbitrary restrictions. Functions can be created and modified dynamically during computation. Functions are first-class values.
Higher-Order Functions As other first-class values, functions can be passed as arguments and returned as values. A function is called a higher-order function if it has function parameters or returns functions.
Scheme: A Dialect of Lisp The development of Lisp begins in 1958. Lisp is based on the lambda calculus. Lisp was called Lisp (List processor) because its basic data structure is a list. Unfortunately, no single standard evolved for the Lisp language, and many different dialects have been developed over the years. Scheme is one of the dialects of Lisp.
Starting Scheme We will use the MIT Scheme interpreter to illustrate the features of Scheme. When we start the MIT Scheme interpreter, we will enter the Read-Eval-Print Loop (REPL) of the interpreter. It displays a prompt whenever it is waiting for your input. You then type an expression. Scheme evaluates the expression, prints the result, and gives you a prompt.
An Example 1 ]=> 12 ;Value: 12 1 ]=> foo ;Unbound variable: foo ;To continue, call RESTART with an option number: ; (RESTART 3) => Specify a value to use instead... ; (RESTART 2) => Define foo to a given value. ; (RESTART 1) => Return to read-eval-print level 1. 2 error>
Leaving Scheme You can leave Scheme by calling the procedure exit. 1 ]=> (exit) Kill Scheme (y or n)? y
Scheme Syntax The syntax of Scheme is particularly simple: expression atom | list atom number | string | identifier | character | boolean list ‘(’ expression-sequence ‘)’ expression-sequence expression expression-sequence | expression
Some Examples 42 a number “hello” a string hello an identifier #\a a character #t the Boolean value “true” (2.1 2.2 2.3) a list of numbers (+ 2 3) a list consisting of an identifier “+” and two numbers
Scheme Semantics A constant atom evaluates to itself. An identifier evaluates to the value bound to it. A list is evaluated by recursively evaluating each element in the list as an expression (in some unspecified order); the first expression in the list evaluates to a function. This function is then applied to the evaluated values of the rest of the list.
Numerical Operations The following are type predicates: (number? x);(number? 3+4i) (complex? x);(complex? 3+4i) (real? x);(real? -0.25) (rational? x);(rational? 6/3) (integer? x);(integer? 3.0)
Numerical Operations The following are relational operators: (= x y z …) ( x y z …) ( = x y z …)
Numerical Operations The following are more predicates: (zero? x) (positive? x) (negative? x) (odd? x) (even? x)
Numerical Operations The following are arithmetic operators: (+ x …);(+ 3 4 5) (* x …);(* 3 4 5) (- x …);(- 3 4 5) (/ x …);(/ 3 4 5) (max x y …);(max 3 4 5) (min x y …);(min 3 4 5)
Numerical Operations The following are arithmetic operators: quotientremaindermodulo absnumeratordenominator gcdlcmfloor ceilingtruncateround explogsqrt
Boolean Operations The following are boolean operations: (boolean? x);(boolean? #f) (not x);(not 3) (and x …);(and 3 4 5) (or x …);(or 3 4 5)
Pairs A pair (sometimes called a dotted pair) is a record structure with two fields called the car (contents of the address register) and cdr (contents of the decrement register) fields. (4. 5) x car xcdr x 4 5
Lists Pairs are used primarily to represent lists. A list is an empty list or a pair whose cdr is a list (); () (a. ()); (a) (a. (b. ())); (a b)
Literal Expressions (quote x) evaluates to x. (quote a); a (quote (+ 1 2)); (+ 1 2) (quote x) may be abbreviated as ‘x. ‘a; a ‘(+ 1 2); (+ 1 2)
List Operations (cons x y); return a pair whose car is x and cdr is y (cons ‘a ‘(b c)); (a b c) (cons ‘(a) ‘(b c)); ((a) b c) (car x); return the car field of x (car ‘(a b c)); a (car ‘((a) b c)); (a) (cdr x); return the cdr field of x (cdr ‘(a b c)); (b c) (cdr ‘((a) b c)); (b c)
List Operations (caar x); (caar ‘((a) b c)) (cadr x); (cadr ‘((a) b c)) (pair? x); (pair? ‘(a b c)) (null? x); (null? ‘(a b c)) (length x); (length ‘(a b c)) (list x …); (list ‘a ‘b ‘c) (append x …); (append ‘(a) ‘(b) ‘(c)) (reverse x); (reverse ‘(a b c))
Conditionals (if test consequent) (if test consequent alternate) (if (> 3 2) ‘yes ‘no) (if (> 3 2) (- 3 2) (+ 3 2)) Special form Evaluation of arguments are delayed
Function Definition Functions can be defined using the function define (define (variable formals) body) (define (gcd u v) (if (= v 0) u (gcd v (remainder u v)) ) )
An Example (append ‘(1 2 3) ‘(4 5 6));(1 2 3 4 5 6) (define (append x y) (if (null? x) y (cons (car x) (append (cdr x) y)) ) )
An Example (reverse ‘(1 2 3)); (3 2 1) (define (reverse x) (if (null? x) x (append (reverse (cdr x)) (cons (car x) ‘())) ) )
Tail Recursion A recursion is called tail recursion if the recursive call is the last operation in the function definition. (define (gcd u v) (if (= v 0) u (gcd v (remainder u v)) ) ) Scheme compiler or interpreter will optimize a tail recursion into a loop.
An Example (define (reverse x) (if (null? x) x (append (reverse (cdr x)) (cons (car x) ‘())) ) ) (define (reverse x) (reverse1 x ‘())) Accumulator (define (reverse1 x y) (if (null? x) y (reverse1 (cdr x) (cons (car x) y))) ) )
Lambda Expressions The value of a function is represented as a lambda expression. (define (square x) (* x x)) (define square (lambda (x) (* x x))) A lambda expression is also called an anonymous function
An Example (define gcd (lambda (u v) (if (= v 0) u (gcd v (remainder u v)) ) ) )
Higher-Order Functions The procedure (apply proc args) calls the procedure proc with the elements of args as the actual arguments. Args must be a list. (apply + ‘(3 4)) ; 7 (apply (lambda (x) (* x x)) ‘(3)) ; 9
Higher-Order Functions The procedure (map proc list 1 list 2 …) applies the procedure proc element-wise to the elements of the lists and returns a list of the results. (map cadr ‘((a b) (d e) (g h))) ; (b e h) (map (lambda (x) (* x x)) ‘(1 2 3)) ; (1 4 9)
Higher-Order Functions An example of returning lambda expressions is as follows: (define (make-double f) (lambda (x) (f x x))) (define square (make-double *)) (square 2)
Equivalence Predicates (eqv? obj1 obj2) returns #t if obj1 and obj2 are the same object (eqv? ‘a ‘a) (eqv? (cons 1 2) (cons 1 2) (equal? obj1 obj2) returns #t if obj1 and obj2 print the same (equal? ‘a ‘a) (equal? (cons 1 2) (cons 1 2)
Input and Output the function read reads a representation of an object from the input and returns the object (read) the function write writes a representation of an object to the output (write object)
Load Programs Functions and expressions in a file can be loaded into the system via the function load (load filename) (load “C:\\user\\naiwei\\ex.txt”)