CSC324 Functional Programming Introducing Scheme

Preview:

Citation preview

CSC324Functional ProgrammingIntroducing Scheme

Afsaneh Fazly1

January 16, 2013

1Thanks to A.Tafliovich, P.Ragde, S.McIlraith, E.Joanis, S.Stevenson, G.Penn, D.Horton

1

Functional Programming

Design goals: mimic mathematical functions as much as possible.Recall from first class:

• program statements are noun phrases describing values ofexpressions.

• key operations are expression evaluation by applying afunction.

• declarative: specifying what to compute (as in a mathematicalfunction) as opposed to specifying how to compute something.

• variables are logical variables (in a mathematical sense), notnicknames for memory locations.

2

Functional Programming

Design goals: mimic mathematical functions as much as possible.Recall from first class:

• program statements are noun phrases describing values ofexpressions.

• key operations are expression evaluation by applying afunction.

• declarative: specifying what to compute (as in a mathematicalfunction) as opposed to specifying how to compute something.

• variables are logical variables (in a mathematical sense), notnicknames for memory locations.

=⇒ more abstract (higher-level) than imperative programming.

2

Scheme expressions

• A number is an expression. More generally, any Scheme valueis an expression.

<expr> ::= <val>

3

Scheme expressions

• A number is an expression. More generally, any Scheme valueis an expression.

<expr> ::= <val>

• The application of a function to some number of argumentexpressions is an expression.

<expr> ::= ( <id> <expr> ... )

• (+ 1 2)• (+ (* 3 4) (- 6 5))

3

Scheme expressions

• A number is an expression. More generally, any Scheme valueis an expression.

<expr> ::= <val>

• The application of a function to some number of argumentexpressions is an expression.

<expr> ::= ( <id> <expr> ... )

• (+ 1 2)• (+ (* 3 4) (- 6 5))

Scheme provides some primitive (built-in) numericfunctions (e.g. /, quotient, remainder, expt).

3

Scheme data types

• number: { 5, -7, 3.14, ... }Includes integers, rationals, reals, and complex numbers.These types are not disjoint, they form a hierarchy.

4

Scheme data types

• number: { 5, -7, 3.14, ... }Includes integers, rationals, reals, and complex numbers.These types are not disjoint, they form a hierarchy.

• symbol: {a, ABC, foo, ...}

4

Scheme data types

• number: { 5, -7, 3.14, ... }Includes integers, rationals, reals, and complex numbers.These types are not disjoint, they form a hierarchy.

• symbol: {a, ABC, foo, ...}

• pair: {(1 . 2), (1.12 . -4), (1 . a), ...}

4

Scheme data types

• A pair looks like this:’( 1 . 2 )

1

2

• Constructor : cons.

• (cons 1 2)

• (cons (cons 1 2) 3)

• Selectors : car, cdr.

• (car ’(1 . 2))

• (cdr ’((1 . 2) . 3))

• (car 1)

• (cdr ’())

5

Scheme data types

• list: {(), (1), (a b), (1 2 foo 3.14), ...}

• The only list that is not a pair is () .

• If L is a list and V is a Scheme value, then (cons V L)

is a list.

• (cons 1 ’())

• (cons ’(1) ’(2 3))

• (car ’(1))

• (cdr ’(1))

• (cdr ’(1 2 3))

• Better selector names for lists: first, rest.

• Other useful selectors: second (cadr), third (caddr),

....

6

definition

<defn> ::= (define <id> <expr>)

A definition binds a name (i.e., an identifier) to a value (result ofthe evaluation of an expression).

(define x 7) ;; binds x to 7

(define y (* x x)) ;; binds y to 49

A subsequent use of the name results in a substitution of theassociated value.

7

values and evaluation

• number: it’s own value

8

values and evaluation

• number: it’s own value

• (quote expr) : expr’expr : shortcut for (quote expr)

8

values and evaluation

• number: it’s own value

• (quote expr) : expr’expr : shortcut for (quote expr)

• lists:• (f . (arg0 ... argN)) and (f arg0 ... argN)

have the valuef (arg0, ..., argN)

This is called prefix notation.

8

Read-Eval-Pint (REP) loop

Read: Read input from user.

Eval: Evaluate input.Lists are evaluated as follows:(f arg0 arg1 ...argn)

1. Evaluate f (a procedure) and each argi (in anunspecified order).

2. Apply procedure to argument values.

Print: Print resulting value:the result of the procedure application.

9

Racket (PLT-Scheme) on CDF

• Type drracket. This starts up DrRacket, the Racketprogramming environment.

• Choose “Use the language declared in the source” in theLanguage menu.

• Start your file with #lang scheme.

• Browse the documentation in HelpDesk,or see:http://docs.racket-lang.org/guide/

10

Read-Eval-Pint loop — Racket (PLT Scheme)

Read: Read input from user.

Eval: Evaluate input.Lists are evaluated as follows:(f arg0 arg1 ...argn)

1. Evaluate f (a procedure).2. Evaluate each argi (in left-to-right order).3. Apply procedure to argument values.

Print: Print resulting value:the result of the procedure application.

11

Read-Eval-Print loop example — Racket (PLT Scheme)

(cons ’a (cons ’b ’(c d))) => (a b c d)

1. Read the input(cons ’a (cons ’b ’(c d))).

2. Evaluate cons : obtain a procedure.

3. Evaluate ’a : obtain a .

4. Evaluate (cons ’b ’(c d)):

4.1 Evaluate cons : obtain a procedure.4.2 Evaluate ’b : obtain b.4.3 Evaluate ’(c d) : obtain (c d).4.4 Apply the cons procedure to b and (c d) : obtain (b c d).

5. Apply the cons procedure to a and (b c d) :obtain (a b c d).

6. Print the result of the application:(a b c d).

12

evaluation by substitution

(+ (* 3 4) (- 6 5))

=> (+ 12 (- 6 5))

=> (+ 12 1)

=> 13

Substitution model:• an expression is reduced to a value by repeatedly finding theleftmost expression ready for substitution, and replacing itwith its value.

• an expression is ready for substitution if all its arguments arevalues.

The substitution model provides good intuition for the purefunctional part of Scheme.

13

values and evaluation

• lists:• (f . (arg0 ... arg N))

has valuef (arg0, ..., argN)

Not all lists have values, e.g.:

(1 2 3) => ?

14

values and evaluation

• lists:• (f . (arg0 ... arg N))

has valuef (arg0, ..., argN)

Not all lists have values, e.g.:

(1 2 3) => ?

1 evaluates to 1, which is not a procedure and cannot be appliedto 2 and 3.

14

values and evaluation

• lists:• (f . (arg0 ... arg N))

has valuef (arg0, ..., argN)

Not all lists have values, e.g.:

(1 2 3) => ?

1 evaluates to 1, which is not a procedure and cannot be appliedto 2 and 3.

Note: ’(1 2 3) has value (1 2 3)

14

Scheme data types

• number: 5, -7, 3.14, 3+4i

Some useful procedures:• type predicates: number?, integer?, real?, complex?• other predicates: positive?, negative?, zero?, even?,odd?, ...

• arithmetic operations: +, -, *, /, floor, remainder, ...• comparison predicates: =, <, <=, >, >=

15

Scheme data types

• number: 5, -7, 3.14, 3+4i

> (define n1 (+ 5 6.7))

> n1

11.7

> (define n2 (- 1 n1))

> n2

-10.7

> (integer? n2)

#f

> (real? n1)

#t

> (positive? n2)

#f

> (>= n1 n2)

#t

16

Scheme data types

• symbol: a, ABC, foo

Some useful procedures:• type predicate : symbol?• comparison predicate: eq? (also eqv?)• display: write, display

17

Scheme data types

• symbol: a, ABC, foo

> (define s1 ’aaa)

> (define s2 ’b)

> (symbol? s1)

#t

> (symbol? n1)

#f

> (eq? s1 s2)

#f

>

18

evaluation: symbols and numbers

> (define x ’y)

> (define y 5)

> (define z y)

> (+ y 1)

> (+ z 1)

> (+ x 1)

19

evaluation: symbols and numbers

> (define x ’y)

> (define y 5)

> (define z y)

> (+ y 1)

6

> (+ z 1)

6

> (+ x 1)

+: contract violation

expected: number?

given: ’y

argument position: 1st

other arguments...:

1

>

20

Scheme data types

• boolean: {#t, #f}.useful synonyms: true, false

Some useful procedures:• type predicate: boolean?• comparison predicates: boolean=?, eq?• logical operations: not, or, and, · · ·

21

special forms

special forms: ( syntactic-keyword expr )

Some syntactic keywords: and, or, if, cond.

<expr> ::= (and { <expr> } )

<expr> ::= (or { <expr> } )

22

special forms (control flow) — if

Syntax:<expr> ::= (if <expr> <expr> <expr>)

Semantics:

(if condition then-expr else-expr)

1. Evaluate condition.

2. If result is not #f, evaluate then-expr.

3. Otherwise, evaluate else-expr.

> (if false (car ’()) 42)

42

23

special forms (control flow) — cond

Syntax:<expr> ::= (cond {(<expr> <expr>)} [(else <expr>)])

Semantics:(cond (cond0 expr0) (cond1 expr1) .... (else exprN))

• Evaluate cond0.

• If the result is not #f, evaluate expr0.

• Otherwise, evaluate cond1.

• If the result is not #f, ...

More syntactic keywords: define, quote, lambda.

24

basic data types

Basic data types in Scheme are:

• pair: (1 . 2), (#t . #f), (1 . #t)

• list: (), (1), (a b), (1 2 foo 3.14)

Useful procedures:

• predicates: list?, pair?, null? (empty?)

• selection: car, cdr, cadr, caadr, cadddr, ...

• list selection: first, rest, second, third, ...

• construction: cons, list, ...

• more: length, append, member, ...

• higher-order: map, apply, foldr, foldl, filter...

25

Scheme data types

• procedure

• type predicate: procedure?

Syntax:<expr> ::= (lambda ({<id>}) <expr>)

Semantics:(lambda (<arg0> ... <argN>) <procedure-body>)

26

Scheme data types: procedure

A lambda expression produces a function (or procedure):

> (lambda (x y) (+ x y))

#<procedure>

27

Scheme data types: procedure

A lambda expression produces a function (or procedure):

> (lambda (x y) (+ x y))

#<procedure>

To apply a procedure (lambda expression) to a list of arguments:

( (lambda (arg0 ... argN) (body)) value0 ... valueN )

> ( (lambda (x y) (+ x y)) 2 3 )

5

28

Scheme data types: procedure

A lambda expression produces a function (or procedure):

> (lambda (x y) (+ x y))

#<procedure>

To apply a procedure (lambda expression) to a list of arguments:

( (lambda (arg0 ... argN) (body)) value0 ... valueN )

> ( (lambda (x y) (+ x y)) 2 3 )

5

To give the procedure a name, use define as before:

(define proc-name (lambda-expr))

> ( define addxy (lambda (x y) (+ x y)) )

29

Scheme data types: procedure

A lambda expression produces a function (or procedure):

> (lambda (x y) (+ x y))

#<procedure>

To apply a procedure (lambda expression) to a list of arguments:

( (lambda (arg0 ... argN) (body)) value0 ... valueN )

> ( (lambda (x y) (+ x y)) 2 3 )

5

To give the procedure a name, use define as before:

(define proc-name (lambda-expr))

> ( define addxy (lambda (x y) (+ x y)) )

> (addxy 2 3)

5

30

indentation

Write code so that it is readable by other human beings.

(define max

(lambda (x y)

(if (> x y) x y)))

(define myproc

(lambda (lst)

(cond ((null? lst) true)

(else false))))

Use a good editor: it will take care of indentation for you.

31

module basics

(module <module-name> scheme

; some comments here

(define myprocedure

(lambda (<args>) (<body>))

)

(define anotherproc

(lambda (<args>) (<body>))

)

(provide myprocedure)

)

• Typically, each Scheme module is in a separate file.• provide explicitly exports myprocedure.• anotherproc is private to the module.

32

simple examples

Define a procedure myabs that takes a number x, and returns itsabstract value, e.g.: (myabs -4.25) --> 4.25

Define a procedure sum-all that takes a flat list of numbers, lst,and returns the sum of all elements in lst, e.g.:

(sum-all ’(1 2 3 4)) --> 10

The sum of elements in a list is:

• 0 if the list is empty,

• first element of the list added to the sum of all elements inthe rest of the list.

33

simple examples: solutions

(define myabs

(lambda (x)

(if (positive? x) (x) (- x))))

(define sum-all

(lambda (lst)

(cond ((null? lst) 0)

(else (+ (first lst)

(sum-all (rest lst)))))))

34

example: sum-all for a nested list

What if the list can be nested?

35

example: sum-all for a nested list

What if the list can be nested?

(define sum-all

(lambda (lst)

(cond ((empty? lst) 0)

((list? (first lst)) (+ (sum-all (first lst))

(sum-all (rest lst))))

(else (+ (first lst)

(sum-all (rest lst)))))))

OR:

(define sum-all

(lambda (lst)

(cond ((not (list? lst)) lst)

((empty? lst) 0)

(else (+ (sum-all (first lst))

(sum-all (rest lst)))))))

36

example: compare lists

Define a procedure eqlist? that takes two lists l1 and l2 asarguments, and returns true iff the two lists are equal.

(eqlist? ’() ’()) --> #t

(eqlist? ’(1 3 4) ’(1 2 3 4)) --> #f

Two lists are equal iff:

• both are empty, or

• their first elements are equal, and their rests are equal lists.

37

compare lists: solution

(define eqlist?

(lambda (l1 l2)

(cond ((and (null? l1) (null? l2)) true)

((or (null? l1) (null? l2)) false)

(else (and (eqv? (first l1) (first l2))

(eqlist? (rest l1) (rest l2)))))))

What if the lists can be nested?

38

example: compare nested lists

Two (nested) lists are equal iff:

• both are empty, or

• first elements are equal atoms, and rests are equal lists, or

• first elements are equal lists, and rests are equal lists.

39

compare nested lists: solution

(define atom?

(lambda (x)

(not (list? x))))

(define eqlist?

(lambda (l1 l2)

(cond ((and (null? l1) (null? l2)) true)

((or (null? l1) (null? l2)) false)

((and (atom? l1) (atom? l2)) (eqv? l1 l2))

(else (and (eqlist? (first l1) (first l2))

(eqlist? (rest l1) (rest l2)))))))

40

example: get length of a list

Define a procedure lenlist that takes a list lst as argument, andreturns its length (number of elements in the list), e.g.:

(lenlist ’()) --> 0

(lenlist ’(1 2 3 4)) --> 4

(lenlist ’(1 (2 3) 4)) --> 3

Length of a list lst is:

• 0 if lst is empty, or

• 1 (for first element) plus the length of the rest of lst

41

example: reverse a list

Define a procedure revlist that takes a list lst as argument, andreturns the reverse of the list:

(revlist ’()) --> ’()

(revlist ’(1 2 3 4)) --> ’(4 3 2 1))

(revlist ’(1 (2 3) 4)) --> ’(4 (2 3) 1))

Reverse of a list lst is:

• empty if lst is empty, or

• reverse of the rest of lst followed by the first element of lst.

42

list examples: solution

(define lenlist

(lambda (lst)

(cond ((empty? lst) 0)

(else (+ 1 (lenlist (rest lst)))))))

(define revlist

(lambda (lst)

(cond ((empty? lst) ’())

(else (append (revlist (rest lst))

(list (first lst)))))))

43

Recommended