26
1 Introduction to Functional Programming in Racket CS 270 Math Foundations of CS Jeremy Johnson

Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

1

Introduction to Functional Programming in Racket

CS 270 Math Foundations of CSJeremy Johnson

Page 2: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

2

Objective To introduce functional programming in racket

Programs are functions and their semantics involve function application. Programs may also produce function by returning functions as values. In pure functional programming, this is it, there are no variables, side effects, nor loops. This simplifies semantics but does not reduce computational power.

We will investigate the style of programming this implies and how to model the semantics of such programs.

Page 3: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

3

Outline

1. Syntax and semantics2. Functional programming

1. Programs are functions – for every input there is a unique output (referential transparency)

2. No variables ⇒ no assignment and no loops3. Use recursion for iteration4. Functions are first class objects

1. Pass as arguments and return as values

3. Racket language and Dr. Racket IDE

Page 4: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

A Pure Functional Language

x1 = y1,…,xn=yn ⇒ f(x1,…,xn) = f(y1,…,yn)

No side-effects, no assignments, no state, no loops

Use recursion instead of iteration Still Turing completeMakes reasoning about programs easier

4

Page 5: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

C++ Function with Side-Effects#include <iostream>

using namespace std;

int cc()

{

static int x = 0;

return ++x;

}

int main()

{

cout << "cc() = " << cc() << endl;

cout << "cc() = " << cc() << endl;

cout << "cc() = " << cc() << endl;

} 5

% g++ count.c

% ./a.out

cc() = 1cc() = 2cc() = 3

Page 6: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

6

Syntax

Programs and data are lists – delimited by ( and ) or [ and ] and separated by space

S expressions (E1 … En) Special forms Self evaluating: numbers, Booleans, strings, … (quote expr) (if test-expr then-expr else-expr) (cond ([P1 E1] … [Pt Et])) (lambda (p1 … pn) E1 … Et) (define name E) (let ([b1 v1] … [bt vt] E)

Page 7: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

7

Semantics

To evaluate (E1 E2 ... En), recursively evaluate E1, E2,...,En - E1 should evaluate to a function -and then apply the function value of E1 to the arguments given by the values of E2,...,En.

In the base case, there are self evaluating expressions (e.g. numbers and symbols). In addition, various special forms such as quote and if must be handled separately.

Page 8: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

8

Read-Eval-Print-Loop (REPL)

Dr. Racket IDE (racket-lang.org)

Definition Window

Click Run to load andrun definitions

Interaction Window

Enter expressions atthe prompt (REPL)

Presenter
Presentation Notes
Students should download DrRacket from racket-lang.org. There are lots of resources for learning Racket and DrRacket available at this website. After installing DrRacket, students can access extensive documentation.
Page 9: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Example Evaluation> 2 => 2

> (/ 4 6) => 23

> + => #<procedure:+>> (+ 2 (* 3 4)) => (+ 2 12) => 14> (max 1 2 3) => 3> (1 2 3) => error> (list 1 2 3) => ‘(1 2 3)> (list 1 (2 3) 4) => error> (list 1 (list 2 3) 4) => ‘(1 (2 3) 4)

Page 10: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Booleans and Predicates

• Boolean constants: #t and #f > (= 2 3) => #f> (or (= 2 3) (not (= 2 3))) => #t> (and #t #t #t) => #t

• Predicates are Boolean functions• Convention is name?> (equal? 2 3) => #f> (eq? 2 3) => #f> (number? 2) => #t> (boolean? (and #t #f)) => #t

Presenter
Presentation Notes
Each type has a predicate to recognize elements of that type. E.G. number? Note that there are different types of numbers, such as integer, rational, and floating point with their corresponding predicates integer?, Rational? and flonum?. The predicate equal? Checks for equality of arbitrary Racket objects, whereas the predicate eq? checks for equality of symbols.
Page 11: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Conditional

(if test-expr then-expr else-expr) Evaluate test-expr if not #f evaluate and

return then-expr else evaluate and return else-expr

> (if (< 2 3) 0 1) => 0> (if (< 3 2) 0 1) => 1> (if (= 3 (+ 2 1)) 0 1) => 0> (if (or (= 2 3) (= 3 3))

(+2 3) (+ 3 3)) => 5

Page 12: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Conditional

(cond [test-expr1 then-body1][test-exprn then-bodyn][else then-body])

Evaluate test-expr1 if #f then goto next case otherwise return then-body1. The else case always returns then-body

> (cond [(= 2 3) 2][(= 3 4) 3][else 4]) => 4

Page 13: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

List Processing Functions

> (null? ‘()) => #t> (null? ‘(1 2 3)) => #f> (car ‘(1 2 3)) => 1 ;same as (first ‘(1 2 3))> (cdr ‘(1 2 3)) => ‘(2 3) ;same as (rest ‘(1 2

3))> (cons 1 ‘()) => ‘(1)> (cons 1 ‘(2 3)) => ‘(1 2 3)> (cons 1 (cons 2 (cons 3 '()))) => ‘(1 2 3)> (cons (cons 1 ‘()) ‘(2 3)) => ‘((1) 2 3)

Page 14: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Lambda Expressions

(lambda (parameters) body) Evaluates to a function When applied the actual arguments are

substituted for the formal parameters into the body which is then evaluated and returned

> (lambda (x) (* x x)) => #<procedure>> ((lambda (x) (* x x)) 2) => 4> (define sqr (lambda (x) (* x x)))> (define (sqr x) (* x x)) ;shorthand for above> (sqr 2) => 4

Page 15: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Recursion

In a functional language there are no side effects, hence no assignment and no loops.

All control must be done through recursion> (define (fact n)

(if (= n 0) 1 (* n (fact (- n 1)))))> (fact 3) => 6> (define (ones n)

(if (= n 0) '() (cons 1 (ones (- n 1)))))> (ones 3) => ‘(1 1 1)

Presenter
Presentation Notes
Recursive functions, like fact, are closely related to definitions of what is being computed. Recursive programming, when you get used to it, is much closer to declarative programming, which states what is to be computed rather than how it is computed.
Page 16: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Trace Recursion

> (define (fact n) (if (= n 0) 1 (* n (fact (- n 1)))))

(fact 0) = 1 (fact 3) = (* 3 (fact 2)) = (* 3 (* 2 (fact 1))) = (* 3 (* 2 (* 1 (fact 0))))= (* 3 (* 2 (* 1 1))) = 6When n=0 [base case] no recursion When n>0 [recursive case] recursion occurs

Page 17: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Recursion

> (define (fact n) (if (= n 0) 1 (* n (fact (- n 1)))))

Similar to mathematical definition – define what to compute

𝑛𝑛! = � 1 𝑤𝑤𝑤𝑤𝑤𝑛𝑛 𝑛𝑛 = 0𝑛𝑛 � 𝑛𝑛 − 1 !𝑤𝑤𝑤𝑤𝑤𝑛𝑛 𝑛𝑛 > 0

Declarative programming states what to compute rather than how to compute it

Page 18: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Tail Recursion

A tail recursive function is a function where the recursive call is the last operation. Such procedures can easily be converted to loops.

> (define (fact n) (if (= n 0) 1 (* n (fact (- n 1)))))

> (define (factt n sofar)> (if (= n 0) sofar

(factt (- n 1) (* n sofar)))))(fact n) = (factt n 1)

Presenter
Presentation Notes
Students may have “learned” that recursion is slow. The point of mentioning tail recursion is that in many cases it is possible to automatically convert recursion to loops. Racket does this for tail recursive functions. The point is that when it is natural students should not fear using recursion. Note that the function sum is not tail recursive since + is called after the recursive call; however, by passing an extra argument which keeps track of the sum so far, it is possible to convert sum to a tail recursive function.
Page 19: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Tail Recursion

An equivalent loop can be constructed, which updates the arguments each iteration of the loop.

for (;;){

if (n == 0)

return sofar;

else {

t1 = n - 1;

t2 = sofar * n;

n = t1;

sofar = t2; } }

Page 20: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Testing

Test cases give examples of what a function should compute if implemented properly. They can be used for debugging. (fact 3) = 6 (fact 2) = 2 (fact 1) = 1 (fact 0) = 1

Page 21: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

Unit Testing in Racket(require rackunit)

(require rackunit/text-ui)

(define-test-suite fact-suite

(check-equal? (fact 0) 1)

(check-equal? (fact 1) 1)

(check-equal? (fact 2) 2)

(check-equal? (fact 3) 6)

)

(run-tests fact-suite 'verbose)

4 success(es) 0 failure(s) 0 error(s) 4 test(s) run

0

Page 22: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

22

Higher Order Functions

sort:

> (sort '(4 3 2 1) <) => (1 2 3 4)> (sort '("one" "two" "three" "four") string<?) => '("four" "one" "three" "two")

map: > (map sqr '(1 2 3 4)) => ‘(1 4 9 16)

Presenter
Presentation Notes
Higher order functions, are functions that have arguments that are functions and/or return functions as results. Sort and map are examples of higher order functions. Note that by passing a comparison function to sort, it is possible to use the same function to sort different types of objects. The function map applies a given function to the elements of a list to return a new list obtained by applying the function to each of the elements of the original list. This is a useful operation that can be combined with other higher order functions such as fold (next slide) to accomplish many different tasks. The function fold is also called reduce and the paradigm of programming with map and reduce is very powerful and is the motivation behind Apache Hadoop.
Page 23: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

23

Higher Order Functionsfilter: > (filter odd? '(1 2 3 4 5)) => ‘(1 3 5)> (filter even? ‘(1 2 3 4 5)) => ‘(2 4)

fold: > (foldr cons '() '(1 2 3 4)) => ‘(1 2 3 4)> (foldr list '() '(1 2 3 4)) => '(1 (2 (3 (4 ()))))> (foldr + 0 '(1 2 3 4)) => 10> (foldl cons ‘() ‘(1 2 3 4)) => ‘(4 3 2 1)> (foldl list '() '(1 2 3 4)) => '(4 (3 (2 (1 ()))))> (foldl * 1 ‘(1 2 3 4)) => 24

Presenter
Presentation Notes
Filter applies a given function, which must be a predicate, to the elements of a list and returns a new list of the elements that satisfy the predicate. The foldl functions apply a given function to the first element of a list and the recursive fold of the rest of the elements of a list. Foldr is similar, but works in the opposite direction.
Page 24: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

24

Functions that Return Functions• Make-adder> (define (make-adder x) (lambda (y) (+ x y)))> (define add1 (make-adder 1))> (add1 3) => 4

> (define (make-multiplier x) (lambda (y) (* x y)))> (define double (make-multiplier 2))> (double 3) => 6

Presenter
Presentation Notes
The function make-adder returns a function that addes the given argument x to its input. Recall that a lambda expression evaluates to a function. Thus (lambda (y) (+ x y)) is the function that adds x to the input y.
Page 25: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

25

Function Composition> (define (compose f g) (lambda (x) (f (g x))))

> (define add2 (compose add1 add1))> (add2 3) => 5

> (define getsecond (compose first rest))> (getsecond ‘(1 2 3 4 5)) => 2

Presenter
Presentation Notes
Function composition is an important example of a higher order function that takes two functions as input and returns a new function which is the composition of the two input functions.
Page 26: Introduction to Functional Programming in Racketjjohnson/2016-17/fall/... · To introduce functional programming in racket Programs are functions and their semantics involve function

26

Currying

> (define (curry f a) (lambda (b) (f a b)))

> (define add1 (curry + 1))> (add1 3) => 4

> (define double (curry * 2))> (doulble 3) => 6

Presenter
Presentation Notes
Currying is another important example involving higher order functions. The function curry takes a function f of two inputs and a value a and returns a function of one argument obtained by fixing one of the inputs to f to the value a. This process is called currying.