Download COS220lec52_FP

Document related concepts

Combinatory logic wikipedia , lookup

Lambda calculus definition wikipedia , lookup

Closure (computer programming) wikipedia , lookup

Lambda calculus wikipedia , lookup

Falcon (programming language) wikipedia , lookup

Tail call wikipedia , lookup

Currying wikipedia , lookup

Anonymous function wikipedia , lookup

Lambda lifting wikipedia , lookup

Common Lisp wikipedia , lookup

Lisp (programming language) wikipedia , lookup

Standard ML wikipedia , lookup

Transcript
COS220 Concepts of PLs
AUBG, COS dept
Lecture 52
Programming Styles
(Functional Programming)
Reference: R.Sebesta, Chapter 15
5/1/2017
Assoc. Prof. Stoyan Bonev
1
Introduction to FP
Imperative programming vs. functional
programming
Language applied to functional programming is
LISP – LISt Programming.
It was invented to provide language features for list
processing, the need for which grew out of the
first application in the area of AI, expert systems,
knowledge based systems.
LISP – J.McCarthy, MIT, 1958
Lisp has two main descendants:
Scheme–Sussman, MIT, 1975;
Common Lisp, 1984
Related languages: ML, LCF, Miranda, Haskell
5/1/2017
Assoc. Prof. Stoyan Bonev
2
Lisp source illustrated
A function call is written as a list with the function name or
operator's name first, and the arguments following:
Imperative style
Functional style
f(x, y, z);
5/1/2017
Assoc. Prof. Stoyan Bonev
3
Lisp source illustrated
A function call is written as a list with the function name or
operator's name first, and the arguments following:
Imperative style
Functional style
f(x, y, z);
(f
5/1/2017
x
y
Assoc. Prof. Stoyan Bonev
z)
4
Lisp source illustrated
A function call is written as a list with the function name or
operator's name first, and the arguments following:
Imperative style
Functional style
f(x, y, z);
(f
x
y
z)
sqrt(a);
5/1/2017
Assoc. Prof. Stoyan Bonev
5
Lisp source illustrated
A function call is written as a list with the function name or
operator's name first, and the arguments following:
Imperative style
Functional style
f(x, y, z);
(f
sqrt(a);
(sqrt
5/1/2017
x
y
z)
a)
Assoc. Prof. Stoyan Bonev
6
Lisp source illustrated
A function call is written as a list with the function name or
operator's name first, and the arguments following:
Imperative style
Functional style
f(x, y, z);
(f
sqrt(a);
(sqrt
x
y
z)
a)
10 + 20
5/1/2017
Assoc. Prof. Stoyan Bonev
7
Lisp source illustrated
A function call is written as a list with the function name or
operator's name first, and the arguments following:
Imperative style
Functional style
f(x, y, z);
(f
sqrt(a);
(sqrt
10 + 20
(+
5/1/2017
x
y
z)
a)
10
Assoc. Prof. Stoyan Bonev
20)
8
Lisp source illustrated
A function call is written as a list with the function name or
operator's name first, and the arguments following:
Imperative style
Functional style
f(x, y, z);
(f
sqrt(a);
(sqrt
10 + 20
(+
x
y
z)
a)
10
20)
gcd(a+b, c*d*e);
5/1/2017
Assoc. Prof. Stoyan Bonev
9
Lisp source illustrated
A function call is written as a list with the function name or
operator's name first, and the arguments following:
Imperative style
Functional style
f(x, y, z);
(f
sqrt(a);
(sqrt
10 + 20
(+
gcd(a+b, c*d*e);
(gcd (+ a b) (* c d
5/1/2017
x
y
z)
a)
10
Assoc. Prof. Stoyan Bonev
20)
e))
10
What is FP?
FP is a specific programming style in which:
1/ to write a functional program means to define a
function or a set of functions;
2/ the only activity performed at run time is the
function call statement.
Pure FP is a programming style with
- no memory allocation;
- no assignment statements;
- no loops, no iterative statements;
- no flow charts;
- no imperative (procedure) algorithms.
5/1/2017
Assoc. Prof. Stoyan Bonev
11
Corner stones to evaluate FP
• λ-calculus (after A. Church)
• The LISP PL (invented by J.McCarthy)
• John Backus and his paper
“Can Programming be Liberated from
the von Neumann Style? A Functional
Style and its Algebra of Programs.”,
Com of the ACM, vol21, no8, pp613-641
5/1/2017
Assoc. Prof. Stoyan Bonev
12
Functional Programming
COMPOSITION OF FUNCTIONS
=
PROGRAMS
5/1/2017
Assoc. Prof. Stoyan Bonev
13
Basic principles of FP
Successful Functional Programming needs:
• a fixed set of base, primitive, standard,
generic functions;
• a mechanism to build new more powerful
functions using formerly defined functions
or base set of available functions.
5/1/2017
Assoc. Prof. Stoyan Bonev
14
Examples
Given a base set function: max(x,y)
Task1: compose a function that returns the
greatest among three arguments
greatest(a,b,c)  max(a, max(b,c)) 
max(max(a,b), c) 
max(b, max(a,c))
5/1/2017
Assoc. Prof. Stoyan Bonev
15
Examples
Given a base set function: max(x,y),
greatest(x,y,z)
Task2: compose a function that returns the
greatest among six arguments
max(greatest(a,b,c), greatest(d,e,f))
greatest(max(a,b), max(c,d), max(e,f))
5/1/2017
Assoc. Prof. Stoyan Bonev
16
So, for FP we need:
1/ base set of functions;
2/ mechanism for function composition;
3/ nothing else.
Requirements to the base set of functions:
- effective machine implementation;
- to be easy for use.
5/1/2017
Assoc. Prof. Stoyan Bonev
17
So, for FP we need:
For example, the base set should include functions
for arithmetic operators, like
add(x,y)  x + y
sub(x,y)  x - y
mul(x,y)  x * y
div(x,y)  x / y
Using these four functions, it’s possible an arbitrary
expression to present in functional notation
a+b*c
(2*x + 3*y) / (x-4)
5/1/2017
Assoc. Prof. Stoyan Bonev
18
So, for FP we need:
add(x,y)  x + y
mul(x,y)  x * y
a+b*c
sub(x,y)  x - y
div(x,y)  x / y
is to be transformed to
add(a, mul(b,c) )
5/1/2017
Assoc. Prof. Stoyan Bonev
19
So, for FP we need:
add(x,y)  x + y
mul(x,y)  x * y
sub(x,y)  x - y
div(x,y)  x / y
(2*x + 3*y) / (x-4) is to be transformed
to
div( add( mul(2,x), mul(3,y)) , sub(x,4) )
5/1/2017
Assoc. Prof. Stoyan Bonev
20
Intro to LISP and its dialects
Intro to LISP and its dialects
Before we comment LISP syntax (S-expressions,
atoms, base set of functions) we’ll remind the
List data structure.
List is a basic data structure. It is the only data
structure available in LISP to describe, present
and store program code and data.
Pure LISP data structures: atoms and lists:
• Atoms are symbols that have the form of
identifiers or numeric constants;
• Lists are specified by surrounding/delimiting
their elements within parentheses.
5/1/2017
Assoc. Prof. Stoyan Bonev
22
Lists
Simple lists, in which elements are restricted
to be only atoms, have the form
( A B C D )
Nested list structures are specified same way
(A(BC) D (E (FG)))
The internal representation may be illustrated
on the white board.
5/1/2017
Assoc. Prof. Stoyan Bonev
23
LISP syntax-model of simplicity
Program code and Program data in Lisp have
exactly the same form: parenthesized list.
Consider the list: ( A B C D )
• When interpreted as data, it is a list of four
elements (data items).
• When viewed as code, it is the application
of function named A to its three
arguments B, C, and D.
5/1/2017
Assoc. Prof. Stoyan Bonev
24
The LISP machine infinite loop
The LISP machine infinite loop
Most popular LISP machines (Scheme, Clisp) are
implemented as an interpreter that operates as
infinite loop performing the following three
actions: Read-Eval-Print Loop or REPL
Read;
Evaluate;
Write.
Shortly the Lisp machine repeatedly:
1/ reads an expression typed by the user as a list
except literals and names.
2/ interprets (evaluates) the expression.
3/ displays the resulting value.
5/1/2017
Assoc. Prof. Stoyan Bonev
26
Dialog using the LISP machine
A/ input – numeric literal
=>312 cr
312
5/1/2017
Assoc. Prof. Stoyan Bonev
27
Dialog using the LISP machine
A/ input – numeric literal
=>312 cr
312
B/ input – expression as a call to primitive functions
in a list form. Expressions presented in prefix
notation called Cambridge Polish notation
Example: Ask the Lisp machine to calculate
infix expression 220+370 or in other words to
evaluate the expression
=>(+ 220 370 )
590
5/1/2017
Assoc. Prof. Stoyan Bonev
28
Dialog using the LISP machine
A/ input – numeric literal
=>312 cr
312
B/ input – expression as a call to primitive functions
in a list form. Expressions presented in prefix
notation called Cambridge Polish notation
=>(+ 220 370 )
590
=>(- 90 64 )
26
5/1/2017
Assoc. Prof. Stoyan Bonev
29
Dialog using the LISP machine
A/ input – numeric literal
=>312 cr
312
B/ input – expression as a call to primitive functions
in a list form. Expressions presented in prefix
notation called Cambridge Polish notation
=>(+ 220 370 )
590
=>(- 90 64 )
26
=>(* 25 8 )
200
5/1/2017
Assoc. Prof. Stoyan Bonev
30
Dialog using the LISP machine
A/ input – numeric literal
=>312 cr
312
B/ input – expression as a call to primitive functions
in a list form. Expressions presented in prefix
notation called Cambridge Polish notation
=>(+ 220 370 )
590
=>(- 90 64 )
26
=>(* 25 8 )
200
=>(/ 10 2 )
5
5/1/2017
Assoc. Prof. Stoyan Bonev
31
Combination
List prefix notations like the examples just covered are
called combination(s).
The leftmost list element is the operator.
The rest list elements are the operands.
Two advantages of using such a notation:
• It permits to describe procedures with an arbitrary
number of arguments (operands).
=>(+ 22 44)
=>(+ 3 5 7)
=>(+ 11 22 33 44)
66
15
110
• It permits to embed combinations as arguments.
=>(+ (* 3 5 ) (- 10 6) )
19
No restrictions on the level of embedding.
5/1/2017
Assoc. Prof. Stoyan Bonev
32
Using names in FP
• Imperative programming: Names are
specified using statements to define, declare,
initialize, and assign values to variables.
• FP: Names are specified using special form of a
base function. In Scheme it is named define. In
Clisp it is named setq.
=>(define size 12)
size
It is said, that name size is bound to value of 12.
In general, in its simplest form define serves to
bind a symbol to the value of an expression.
( define symbol expression )
5/1/2017
Assoc. Prof. Stoyan Bonev
33
More examples
=>( define size 2 )
size
5/1/2017
Assoc. Prof. Stoyan Bonev
34
More examples
=>( define size 2 )
size
=>( define pi 3.1415 )
pi
5/1/2017
Assoc. Prof. Stoyan Bonev
35
More examples
=>( define size 2 )
size
=>( define pi 3.1415 )
pi
=>( define two_pi ( * 2 pi ) )
two_pi
5/1/2017
Assoc. Prof. Stoyan Bonev
36
More examples
=>( define
size
=>( define
pi
=>( define
two_pi
=>( define
rad
5/1/2017
size 2 )
pi 3.1415 )
two_pi ( * 2 pi ) )
rad 10 )
Assoc. Prof. Stoyan Bonev
37
More examples
=>( define size 2 )
size
=>( define pi 3.1415 )
pi
=>( define two_pi ( * 2 pi ) )
two_pi
=>( define rad 10 )
rad
=>( * 5 size )
10
5/1/2017
Assoc. Prof. Stoyan Bonev
38
More examples
=>( define size 2 )
size
=>( define pi 3.1415 )
pi
=>( define two_pi ( * 2 pi ) )
two_pi
=>( define rad 10 )
rad
=>( * 5 size )
10
=>( * pi ( * rad rad ) )
314.15
5/1/2017
Assoc. Prof. Stoyan Bonev
39
More examples
=>( define size 2 )
size
=>( define pi 3.1415 )
pi
=>( define two_pi ( * 2 pi ) )
two_pi
=>( define rad 10 )
rad
=>( * 5 size )
10
=>( * pi ( * rad rad ) )
314.15
=>( * pi ( * size rad ) )
62.83
5/1/2017
Assoc. Prof. Stoyan Bonev
40
More examples (cont.)
=>( define circlearea ( * pi rad rad ) )
circlearea
5/1/2017
Assoc. Prof. Stoyan Bonev
41
More examples (cont.)
=>( define circlearea ( * pi rad rad ) )
circlearea
=>circlearea
314.15
5/1/2017
Assoc. Prof. Stoyan Bonev
42
More examples (cont.)
=>( define circlearea ( * pi rad rad ) )
circlearea
=>circlearea
314.15
=>( define circlelen ( * two_pi rad ) )
circlelen
5/1/2017
Assoc. Prof. Stoyan Bonev
43
More examples (cont.)
=>( define circlearea ( * pi rad rad ) )
circlearea
=>circlearea
314.15
=>( define circlelen ( * two_pi rad ) )
circlelen
=>circlelen
62.83
5/1/2017
Assoc. Prof. Stoyan Bonev
44
Functions for constructing functions
In Scheme User defined functions are described using the
same base primitive function define.
In this form define takes two lists as parameters.
The first is the prototype of a function call with the function
name followed by formal parameters, all in a list.
The second list is the expression to which the name is to be
bound.
( define ( <function_name> <parameters> )
<body>
)
<parameters> are separated by space(s), not by comma(s)
and the <body> is a sequence of expressions, all
presented in form of lists.
5/1/2017
Assoc. Prof. Stoyan Bonev
45
Functions for constructing functions
In Clisp User defined functions are described using the base
primitive function defun.
In this form defun precedes the function name and two lists.
The first list includes the function parameters.
The second list is the expression to which the name is to be
bound.
( defun <function_name> ( <parameters> )
<body>
)
<parameters> are separated by space(s), not by comma(s)
and the <body> is a sequence of expressions, all
presented in form of lists.
5/1/2017
Assoc. Prof. Stoyan Bonev
46
Examples
( define ( <function_name> <parameters> )
<body>
)
( define ( sqr x )
(* x x)
)
( define ( cube x )
(* x x x)
)
( define ( reciproc x )
(/ 1 x)
)
5/1/2017
Assoc. Prof. Stoyan Bonev
47
Using the functions defined
• Explicit call for expression calculation
=>(sqr 15)
225
5/1/2017
=>(sqr 21)
441
Assoc. Prof. Stoyan Bonev
=>(sqr (sqr 3))
81
48
Using the functions defined
• Explicit call for expression calculation
=>(sqr 15)
225
=>(sqr 21)
441
=>(sqr (sqr 3))
81
• New functions definition
=>(define (sum_of_squares x y) (+ (* x x) (* y y ) ) )
sum_of_squares
5/1/2017
Assoc. Prof. Stoyan Bonev
49
Using the functions defined
• Explicit call for expression calculation
=>(sqr 15)
225
=>(sqr 21)
441
=>(sqr (sqr 3))
81
• New functions definition
=>(define (sum_of_squares x y) (+ (* x x) (* y y ) ) )
sum_of_squares
=>(sum_of_squares 3 4 )
25
5/1/2017
Assoc. Prof. Stoyan Bonev
50
Using the functions defined
• Explicit call for expression calculation
=>(sqr 15)
225
=>(sqr 21)
441
=>(sqr (sqr 3))
81
• New functions definition
=>(define (sum_of_squares x y) (+ (* x x) (* y y ) ) )
sum_of_squares
=>(sum_of_squares 3 4 )
25
=>(define ( f a ) (sum_of_squares (+ a 1) (* a 2 ) ) )
f
5/1/2017
Assoc. Prof. Stoyan Bonev
51
Using the functions defined
• Explicit call for expression calculation
=>(sqr 15)
225
=>(sqr 21)
441
=>(sqr (sqr 3))
81
• New functions definition
=>(define (sum_of_squares x y) (+ (* x x) (* y y ) ) )
sum_of_squares
=>(sum_of_squares 3 4 )
25
=>(define ( f a ) (sum_of_squares (+ a 1) (* a 2 ) ) )
f
=>(f 5)
136
5/1/2017
Assoc. Prof. Stoyan Bonev
52
Control flow
The computational power of user defined
functions may increase if we introduce a
control flow mechanism instead providing
function calls for linear algorithms.
Let me remind the McCarthy’s conditional
expression [b1->e1,b2->e2, … bn-1->en-1,en]
and its LISP notation in three versions
5/1/2017
Assoc. Prof. Stoyan Bonev
53
First version
( cond ( <b1>
( <b2>
( <bn-1>
( <bn>
<e1> )
<e2> )
...
<en-1> )
<en> )
)
5/1/2017
Assoc. Prof. Stoyan Bonev
54
Second version
( cond ( <b1>
( <b2>
( <bn-1>
( else
<e1> )
<e2> )
...
<en-1> )
<en> )
)
5/1/2017
Assoc. Prof. Stoyan Bonev
55
Third version
( if <predicate>
<then-expression>
<else-expression>
)
5/1/2017
Assoc. Prof. Stoyan Bonev
56
Using conditional expressions
To define function abs(x) = x, if
= 0, if
= -x, if
( define ( abs x )
( cond ( (> x 0 ) x )
( (= x 0 ) 0 )
( (< x 0 ) ( - x)
)
)
5/1/2017
Assoc. Prof. Stoyan Bonev
x>0
x=0
x<0
)
57
Two more versions
( define ( abs x )
( cond ( (< x 0 ) ( - x) )
( else
x)
)
)
5/1/2017
Assoc. Prof. Stoyan Bonev
58
Two more versions
( define ( abs x )
( cond ( (< x 0 ) ( - x) )
( else
x)
)
)
( define ( abs x )
( if (< x 0)
)
5/1/2017
(- x) x )
Assoc. Prof. Stoyan Bonev
59
Logical expressions
Example 1:
5 < x < 10
5/1/2017
Assoc. Prof. Stoyan Bonev
60
Logical expressions
Example 1:
5 < x < 10
(and (> x 5) (< x 10) )
5/1/2017
Assoc. Prof. Stoyan Bonev
61
Logical expressions
Example 2: define own predicate >=
(define (>= x y )
(or (> x y) (= x y) ) )
OR
(define (>= x y ) (not (< x y) ) )
5/1/2017
Assoc. Prof. Stoyan Bonev
62
Recursion in LISP
Function returns sum of n natural numbers
Imperative (C/C++) version:
int sumr(int n){
if (n==0) return n;
else return n + sumr(n-1); }
Functional Lisp list version:
(define (sumr n)
( if (= n 0) 0 (+ n (sumr (- n 1) ) ) )
)
5/1/2017
Assoc. Prof. Stoyan Bonev
63
List Processing
in
LISP
LISP syntax
•
To specify a list:
– ( A B C D ) function call A(B,C,D)
– ‘( A B C D ) list of four data elements
•
5/1/2017
To bind a name to a list
( define lis ‘(A B C D ))
( setq lis ‘(A B C D ))
Assoc. Prof. Stoyan Bonev
65
Primitive list selectors
•
•
List selector car.
car returns the first element (head) of a
list
(car ‘(A B C D ))
(car ‘((A B) C D))
(car ‘A)
(car ‘(A))
5/1/2017
returns A
returns (A B)
is an error
returns A
Assoc. Prof. Stoyan Bonev
66
Primitive list selectors
•
•
List selector cdr.
cdr returns the remainder of a list after its
car is removed
(cdr ‘(A B C D ))
(cdr ‘((A B) C D))
(cdr ‘A)
(cdr ‘(A))
5/1/2017
returns (B C D)
returns (C D)
is an error
returns ( ) – empty list
Assoc. Prof. Stoyan Bonev
67
Primitive list constructor
•
•
List constructor cons.
cons builds a list using its two parameters
(cons ‘A ‘() )
(cons ‘A ‘(B C) )
(cons (car lis) (cdr lis) )
5/1/2017
returns (A)
returns (A B C)
returns lis
Assoc. Prof. Stoyan Bonev
68
Primitive list predicates
•
null(<argument>)
–
•
Returns T (true) if argument is an empty list
atom(<argument>)
–
•
Returns T (true) if argument is an atom
eq(<argument> <argument>)
–
5/1/2017
Returns T (true) if both arguments are the
same, otherwise NIL (false)
Assoc. Prof. Stoyan Bonev
69
Definition of functions on lists
• Function to return the length of a list
( define (len x)
(if (null x)
0
(+ 1 (len (cdr x) ) )
)
)
5/1/2017
Assoc. Prof. Stoyan Bonev
70
Definition of functions on lists
• Function to return the length of a list
( defun len (x)
(if (null x)
0
(+ 1 (len (cdr x) ) )
)
)
5/1/2017
Assoc. Prof. Stoyan Bonev
71
Definition of functions on lists
• Function to return the length of a list
( setq lis ‘(A B C D) )
• Function call
( len lis )
5/1/2017
returns 4
Assoc. Prof. Stoyan Bonev
72
Thank You
For
Your Attention