/
Functional Programming Functional Programming

Functional Programming - PowerPoint Presentation

briana-ranney
briana-ranney . @briana-ranney
Follow
432 views
Uploaded On 2015-10-28

Functional Programming - PPT Presentation

04 Control ControlBlocks Common Lisp has 3 basic operators for creating blocks of code progn block tagbody If ordinary function calls are the leaves of a Lisp program these operators are used to build the branches ID: 175244

values control defun multiple control values multiple defun format nil num year form date month test lst return blocks

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "Functional Programming" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

Functional Programming

04 ControlSlide2

Control-Blocks

Common Lisp has 3 basic operators for creating blocks of code

progn

block

tagbody

If ordinary function calls are the leaves of a Lisp program, these operators are used to build the branchesSlide3

Control-Blocks

> (

progn

(format t “a”)

(format t “b”)

(+ 11 12)

)

ab

23

-> only the value of the last expression is returnedSlide4

Control-Blocks

> (block head

(format t “Here we go.”)

(

return-from

head ‘idea)

(format t “We’ll never see this.”))

Here we go.

IDEA

Calling return-from allows your code to make a sudden but graceful exit from anywhere in a body of code

Expressions after the return-from are not evaluatedSlide5

Control-Blocks

> (block nil

(

return

27))

27

> (dolist (x ‘(a b c d e))

(format t “~A “ x)

(if (eql x ‘c)

(return ‘done)))

A B C

DONESlide6

Control-Blocks

The body of a function defined with

defun

is implicitly enclosed in a

block

with the same name as the function

(

defun

foo

(

)

(return-from

foo

27)

)

(

defun

read-integer

(

str

)

(let

((

accum

0))

(

dotimes

(pos

(length

str

))

(let

((

i

(digit-char-p

(char

str

pos))))

(if

i

(

setf

accum

(+

(

*

accum

10)

i

))

(

return-from

read-integer nil))))

accum

))Slide7

Control-Blocks

Within tagbody, you can use

go

> (

tagbody

(setf x 0)

top

(setf x (+ x 1))

(format t “~A “ x)

(if (< x 10) (

go

top)))1 2 3 4 5 6 7 8 9 10This operator is mainly something that other operators are built upon, not something you would use yourself

Ugly code!!Slide8

Control-Blocks

How to decide which block construct to use?

Nearly all the time you’ll use progn

If you want to allow for sudden exits, use block

Most programmers will never use tagbody explicitlySlide9

Control-Context

let

Takes a body of code

Allows us to establish variables for use

within

the body

> (

let

((x 7)

(y 2))

(format t “Number”)

(+ x y))

Number

9Slide10

Control-Context

>

(

(lambda (x) (+ x 1))

3)

4

(

(lambda (x y)

(format t “Number”)

(+ x y))

7

2)Slide11

Control-Context

One let-created variable can’t depend on other variables created by the same let

(let ((x 2)

(y (+ x 1)))

(+ x y))

((lambda (x y) (+ x y)) 2

(+ x 1))

> (

let*

((x 1)

(y (+ x 1)))

(+ x y))

3

equivalentSlide12

Control-Context

A let* is functionally equivalent to a series of nested lets

(let ((x 1))

(let ((y (+ x 1)))

(+ x y)))

In both let and let*, initial values default to nil

> (let (x y)

(list x y))

(NIL NIL)Slide13

Control- Conditionals

(

if

(oddp that)

(progn

(format t “Hmm, that’s odd.”)

(+ that 1)))

(

when

(oddp that)

(format t “Hmm, that’s odd.”)

(+ that 1))

equivalentSlide14

Control- Conditionals

(if <test> <then form> <else form>)

(if <test> <then form>)

(when <test> <then form>)

(if <test> nil <else form>)

(unless <test> <else form>)Slide15

Control- Conditionals

(defun our-member (obj lst)

(if

(atom lst)

nil

(if

(eql (car lst) obj)

lst

(our-member obj (cdr lst))

))

(defun our-member (obj lst)

(cond (

(atom lst) nil) ((eql (car lst) obj)

lst)

(t

(our-member obj (cdr lst))

)))

equivalent

A Common Lisp implementation will probably implement cond by translating it to the “if” formatSlide16

Control- Conditionals

cond

(

cond

(

<test 1>

<consequent 1-1> …)

(

<test 2>

<consequent 2-1> …)

(

<test m>

<consequent m-1> …));

cond

The conditions are evaluated in order until one of them returns true

When one condition returns true, the expressions associated with it are evaluated in order, and the value of the last is returns as the value of the

cond

> (

cond

(99))

; if there are no expressions after the successful conditio

n

99

; , the value of the condition itself is returned. Slide17

Control- Conditionals

case

(case <key form>

(

<key 1>

<consequent 1-1> …)

(

<key 2>

<consequent 2-1> …)

...

(

<key m>

<consequent m-1> …)

) ;caseSlide18

Control- Conditionals

(

defun

month-length (

mon

)

(

case

mon

(

(

jan

mar may jul aug oct

dec

)

31)

(

(

apr

jun

sept

nov

)

30)

(

feb

(if (leap-year) 29 28))

(

otherwise

“unknown month”)))

Keys

Are treated as constants

Will not be evaluated

> (case 99 (99))

The successful clause contains only keys

NILSlide19

Control- Iteration

do

(do

((<parameter 1> <initial value 1> <update form 1>)

(<parameter 2> <initial value 2> <update form 2>)

(<parameter n> <initial value n> <update form n>))

(<termination test> <intermediate forms, if any> <result form>)

<body>

)

;do

> (let ((x ‘a))

(do ((x 1 (+ x 1))

(y x

x

))

((> x 5))

(format t “(~A ~A) “ x y)))

(1 A) (2 1)

(

3 2) (4 3) (5 4

)

;on each iteration, x gets its previous

NIL

;value plus 1; y also gets the previous

;valueSlide20

Control- Iteration

do*

Has the same relation to

do

as

let*

does to

let

> (do* ((x 1 (+ x 1))

(y x x))

((> x 5))

(format t “(~A ~A) “ x y))

(1 1) (2 2) (3 3) (4 4) (5 5)

NIL Slide21

Control- Iteration

dolist

> (dolist (x ‘(a b c d)

‘done

)

(format t “~A “ x))

A B C D

DONE

dotimes

> (dotimes (x 5

x

)

; for x = 0 to 5-1, return x

(format t “~A “ x))0 1 2 3 4 5Slide22

Control- Multiple values

In Common Lisp, an expression can return zero or more values

E.g.,

get-decoded-time

returns the current time in nine values

value

Returns multiple values

> (values ‘a nil (+ 2 4))

A

NIL

6Slide23

Control- Multiple values

> ((lambda ( )

(values 1 2)

))

1;

2

If something is expecting only one value, all but the first will be discarded

> (let ((x (values 1 2)))

x)

1Slide24

Control- Multiple values

> (values)

returns no value

> (let ((x (values)))

x)

NIL

Use

multiple-value-bind

to receive multiple values

> (

multiple-value-bind

(x y z) (values 1 2 3)

(list x y z))

(1 2 3)

> (

multiple-value-bind

(x y z) (values 1 2)

(list x y z))

(1 2 NIL)Slide25

Control- Multiple values

> (

multiple-value-bind

(s m h) (get-decoded-time)

(format nil “~A:~A:~A” h m s))

“4:32:13”

We can pass on multiple values as the arguments to a second function using

multiple-value-call

> (

multiple-value-call

#’+ (values 1 2 3))

6

multiple-value-lis

t is like using multiple-value-call with #’list as the first argument

> (

multiple-value-list

(values ‘a ‘b ‘c))

(A B C)Slide26

Control-Aborts

catch

and

throw

(defun super ( )

(catch

‘abort

(sub)

(format t “We’ll never see this.”)))

(defun sub ( )

(throw

‘abort

99)

> (super)99Slide27

Control- Example: Date arithmetic

(defconstant month

#(0 31 59 90 120 151 181 212 243 273 304 334 365))

(defconstant yzero 2000)

(defun leap? (y)

(and (zerop (mod y 4))

(or (zerop (mod y 400))

(not (zerop (mod y 100))))))Slide28

Control- Example: Date arithmetic

(defun date->num (d m y)

(+ (- d 1)

(month-num

m y)

(year-num

y)))

(defun

month-num

(m y)

(+ (svref month (- m 1))

(if (and (> m 2) (leap? y)) 1 0)))

(defun

year-num (y)

(let ((d 0))

(if (>= y yzero)

(dotimes (i (- y yzero) d)

(incf d (

year-days

(+ yzero i))))

(dotimes (i (- yzero y) (- d))

(incf d (

year-days

(+ y i)))))))

(defun

year-days

(y) (if (leap? y) 366 365))Slide29

Control- Example: Date arithmetic

(

defun

num->date (n)

(multiple-value-bind (y left) (

num-year

n)

(multiple-value-bind (m d) (

num-month

left y)

(values d m y))))

(

defun

num-year

(n)

(if (< n 0)

(do* ((y (- yzero 1) (- y 1))

(d (- (year-days y)) (- d (year-days y))))

((<= d n) (values y (- n d))))

(do* ((y yzero (+ y 1))

(

prev

0 d)

(d (year-days y) (+ d (year-days y))))

((> d n) (values y (- n

prev

))))))Slide30

Control- Example: Date arithmetic

(

defun

num-month

(n y)

(if (leap? y)

(

cond

((= n 59) (values 2 29))

((> n 59) (

nmon

(- n 1)))

(t (

nmon

n)))

(

nmon

n)))

(

defun

nmon

(n)

(let ((m (position n month :test #’<)))

(values m (+ 1 (- n (

svref

month (- m 1)))))))

(defun date+ (d m y n)

(num->date (+ (date->num d m y) n)))Slide31

Control- Example: Date arithmetic

> (mapcar #’leap? ‘(1904 1900 1600))

(T NIL T)

> (multiple-value-list (date+ 17 12 1997 60))

(15 2 1998)Slide32

Control

Homework (Due April 7)

Rewrite month-mon to use case instead of svref

Define a single recursive function that returns, as two values, the maximum and minimum elements of a vector