Download 15 functional programming2

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Introduction to Higher Order
(Functional Programming) (Python)
part 2
John R. Woodward
Higher Order Function
• A higher order function is a function which
• - take another function as input
Or
• Returns a function as output.
What does the following print
foo = [2, 18, 9, 22, 17, 24, 8, 12,
27]
1. print filter(lambda x: x % 3 == 0,
foo)
2. print map(lambda x: x * 2 + 10,
foo)
3. print reduce(lambda x, y: x + y,
foo)
output
1. [18, 9, 24, 12, 27]
2. [14, 46, 28, 54, 44, 58, 26, 34,
64]
3. 139
What does the following print
foo = [2, 18, 9, 22, 17, 24, 8, 12,
27]
1. print type(filter(lambda x: x % 3
== 0, foo))
2. print type(map(lambda x: x * 2 +
10, foo))
3. print type(reduce(lambda x, y: x +
y, foo))
output
1. <type 'list'>
2. <type 'list'>
3. <type 'int'>
Lambda – filter, map, reduce
foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]
print filter(lambda x: x % 3 == 0, foo)
#[18, 9, 24, 12, 27]
print map(lambda x: x * 2 + 10, foo)
#[14, 46, 28, 54, 44, 58, 26, 34, 64]
print reduce(lambda x, y: x + y, foo)
#139
#(more detail in a few slides)
Lists
• Functional programming uses LISTs as its primary
data structure. E.g. [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
• listNumbers = [1,2,3] #[1,2,3]
• listNumbers.append(4)#[1, 2, 3, 4]
• listNumbers.insert(2, 55)#[1, 2, 55,
3, 4]
• listNumbers.remove(55)#[1, 2, 3, 4]
• listNumbers.index(4)#3
• listNumbers.count(2)#1
Map – (a transformation)
• Map takes a function and a list and applies the function
to each elements in the list
• def cube(x): return x*x*x
• print map(cube, range(1, 11))
• print map(lambda x :x*x*x, range(1, 11))
• print map(lambda x :x*x*x, [1, 2, 3, 4,
5, 6, 7, 8, 9, 10])
• # [1, 8, 27, 64, 125, 216, 343, 512,
729, 1000]
• #what is the type signature
filter
• Filter takes a function (what type???) and a list,
and returns items which pass the test
• def f1(x): return x % 2 != 0
• def f2(x): return x % 3 != 0
• def f3(x): return x % 2 != 0 and x %
3 != 0
1. print filter(f1, range(2, 25))
2. print filter(f2, range(2, 25))
3. print filter(f3, range(2, 25))
filter 2
• def f1(x): return x % 2 != 0
• def f2(x): return x % 3 != 0
• def f3(x): return x % 2 != 0 and x % 3 != 0
•
•
•
•
•
•
•
print filter(f1, range(2, 25))
# [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23]#odd
print filter(f2, range(2, 25))
# [2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23]
#not divisible by 3
print filter(f3, range(2, 25))
# [5, 7, 11, 13, 17, 19, 23]#not divisible by 2 or 3
A list can contain different datatypes
• list1 = [0, 1, 0.0, 1.0, True,
False, "True", "False", "", None,
[True], [False]]
• def isTrue(x):
•
return x
• print filter(isTrue, list1)
output
• list1 = [0, 1, 0.0, 1.0, True,
False, "True", "False", "", None,
[True], [False]]
• #answer
• [1, 1.0, True, 'True', 'False', [True], [False]]
Reduce – try this
•
•
•
•
reduce(
reduce(
reduce(
reduce(
(lambda
(lambda
(lambda
(lambda
x,
x,
x,
x,
y:
y:
y:
y:
x
x
x
x
+
*
/
y),
y),
y),
y),
[1,2,3,4]
[1,2,3,4]
[1,2,3,4]
[1,2,3,4]
)
)
)
)
answers
•
•
•
•
•
•
•
•
reduce(
reduce(
reduce(
reduce(
10
-8
24
0
(lambda
(lambda
(lambda
(lambda
x,
x,
x,
x,
y:
y:
y:
y:
x
x
x
x
+
*
/
y),
y),
y),
y),
[1,
[1,
[1,
[1,
2,
2,
2,
2,
3,
3,
3,
3,
4]
4]
4]
4]
)
)
)
)
The last one
• print reduce( (lambda x, y: x /
y), [1.0, 2.0, 3.0, 4.0] )
• ??? answer
The last one
• print reduce( (lambda x, y: x /
y), [1.0, 2.0, 3.0, 4.0] )
• 0.0416666666667
• # what is the type signature?
Map, Reduce, Filter
1. Map, reduce and filter all take a function as
an argument.
2. What type is the function in each case
3. Map,
4. Reduce,
5. Filter
Data Types of Function Taken.
1. Map: takes an argument of type T and returns a
type S. It returns a list of S, denoted [S]
2. Reduce: takes two arguments of type T, and
returns an argument of type T
3. Filter: take an argument of type T and returns a
Boolean (True/False). It returns a list of T,
denoted [T]
Partial Application
1.
2.
3.
4.
5.
6.
7.
Motivating example
Addition (+) takes two arguments
(arg1 + arg2)
What if we only supply one argument?
We cannot compute e.g. (1+)
But it is still a function of one argument
(1+ could be called what???)
Visualization
???
3
ADD
ADD
2
1
This is how we normally
think of the add function
???
1
Inc as partial add
•
•
•
•
•
•
•
#add (2 args), inc(x)=add(1,x)
#inc is a special case of add
from functools import partial
def add(a,b):
return a+b
inc = partial(add, 1)
print inc(4)
Inc defined with add
• #add takes 2 arguments
• def add(x,y):
•
return x+y
• #we can define a new function by
hardcoding one variable
• def inc(x):
•
return add(1,x)
• print inc(88)
double as partial mul
•
•
•
•
•
•
•
#mul(2 args), double(x)=mul(2,x)
#double is a special case of mul
from functools import partial
def mul(a,b):
return a*b
double = partial(mul, 2)
print double(10)
Functions as special cases
• #square and cube are special cases
of the power function
• def power(base, exponent):
•
return base ** exponent
• def square(base):
•
return power(base, 2)
• def cube(base):
•
return power(base, 3)
Equivalent Code
• from functools import partial
• square = partial(power, exponent=2)
• cube = partial(power, exponent=3)
referential transparency
1. Haskell is a pure functional language
referential transparency - the evaluation of an
expression does not depend on context.
2. The value of an expression can be evaluated in any
order
(all sequences that terminate return the same value)
(1+2)+(3+4) we could reduce this in any order.
3. In the 2nd world war,
Richard Feynman was in charge of making calculation
for the atomic bomb project.
4. These calculations were done by humans working in
parallel. e.g. calculate exponential
Functional Programming
1. Programming paradigm? Object oriented,
imperative
2. Immutable state (referential transparency)
3. Higher order functions, partial functions,
anonymous functions (lambda)
4. Map, filter, reduce (fold)
5. List data structures and recursion feature heavily
6. Type inference (type signatures)
7. Lazy and eager evaluation, list comprehension
State & Referential Transparency
1. In maths, a function depends ONLY ON ITS INPUTS
e.g. root(4) = +/-2
2. This is a “stateless function”
3. A stateful function (method, procedure) stores some
data which changes i.e. mutable data
4. E.g. a “function” which returns the last argument it
was given
5. F(4) = -1, F(55) = 4, F(3) = 55, F(65) = 55,
6. (side effects, e.g. accessing a file)
7. Harder to debug stateful function than stateless
(why).
List Comprehensions
• List comprehensions provide a concise way to
create lists.
• To make new lists, where each element is the
result of some operation applied to each
member of another sequence.
List Comprehensions
• The following are common ways to describe
lists (or sets, or tuples, or vectors) in
mathematics.
S = {x² : x in 0 ... 9}
V = (1, 2, 4, 8, ..., 2¹²)
M = {x | x in S and x even}
Create a list of squares
For example, assume we want to create a
list of squares, like:
• squares = []
• for x in range(10):
•
squares.append(x**2)
• print squares
• #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
As a list comprehension
We can obtain the same result with:
• squares = [x**2 for x in range(10)]
This is also equivalent to
• squares = map(lambda x: x**2, range(10)),
However the list comprehension is more
concise and readable.
(choose the way that works for you, but
do try different techniques)
In Python
• S = [x**2 for x in range(10)]
• V = [2**i for i in range(13)]
• M = [x for x in S if x % 2 == 0]
• print S;
• print V;
• print M
In Python
• S = [x**2 for x in range(10)]
• V = [2**i for i in range(13)]
• M = [x for x in S if x % 2 == 0]
• print S; [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512,
• print V;
1024, 2048, 4096]
• print M [0, 4, 16, 36, 64]
Calculating Primes
1. We can calculate the primes by
2. first build a list of non-prime numbers,
3. then use another list comprehension to get
the "inverse" of the list,
Calculating Primes
noprimes = [j for i in range(2, 8)
for j in range(i*2, 50, i)]
print noprimes
primes = [x for x in range(2, 50)
if x not in noprimes]
print primes
output
• noprimes = [j for i in range(2, 8) for j in
range(i*2, 50, i)]
• print noprimes
• #[4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 6, 9, 12,
15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 8,
12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 10, 15,
20, 25, 30, 35, 40, 45, 12, 18, 24, 30, 36, 42,
48, 14, 21, 28, 35, 42, 49]
• primes = [x for x in range(2, 50) if x not in
noprimes]
• print primes
• #[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47]
Nested List Comprehensions
1. You can nest list comprehensions (just like
you can do with other python commands).
2. In this case just substitute the “noprimes”
variable with the python code.
3. I would not recommend this, as it is harder
to read
4. It is also harder to debug (where would you
insert a print statement)
Nested List Comprehensions
• primes = [x for x in range(2, 50)
if x not in [j for i in range(2,
8) for j in range(i*2, 50, i)]]
• print primes
• #[2, 3, 5, 7, 11, 13, 17, 19, 23,
29, 31, 37, 41, 43, 47]
List Comprehension with Strings
words = 'The quick brown fox jumps
over the lazy dog'.split()
print words
stuff = [[w.upper(), w.lower(),
len(w)] for w in words]
for i in stuff:
print i
List Comprehension with Strings
words = 'The quick brown fox jumps
over the lazy dog'.split()
print words
stuff = [[w.upper(), w.lower(),
len(w)] for w in words]
for i in stuff:
['THE', 'the', 3]
['QUICK', 'quick', 5]
print i
['BROWN', 'brown', 5]
['FOX', 'fox', 3]
['JUMPS', 'jumps', 5]
Output 2
• words = 'The quick brown fox jumps
over the lazy dog'.split()
• stuff = [[w.upper(), w.lower(),
len(w)] for w in words]
• for i in stuff:
•
print i
<type 'list'>
• print type(words)
<type 'list'>
• print type(stuff)
3 EXAMPLES
print [y for y in [3,1,4]]
print [(x, y) for x in [1,2,3] for y
in [3,1,4]]
print [(x, y) for x in [1,2,3] for y
in [3,1,4] if x != y]
OUTPUT
• [3, 1, 4]
• [(1, 3), (1, 1), (1, 4), (2, 3), (2, 1), (2, 4), (3, 3), (3,
1), (3, 4)]
• [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
Written as nested for loops
• [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
Is equivalent to
• combs = []
• for x in [1,2,3]:
•
for y in [3,1,4]:
•
if x != y:
•
combs.append((x, y))
the order of the for and if statements is the same in both
(choose the way that works for you, but do try
different techniques)
More examples
vec = [-4, -2, 0, 2, 4]
1. print [x*2 for x in vec]
2. print [x for x in vec if x >= 0]
3. print [abs(x) for x in vec]
• fruits = [' banana', '
loganberry ', 'passion fruit ']
4. print [fruit.strip() for fruit in
fruits]
5. print [(x, x**2) for x in range(6)]
More examples
vec = [-4, -2, 0, 2, 4]
1. print [x*2 for x in vec]
2. print [x for x in vec if x >= 0]
3. print [abs(x) for x in vec]
More examples
vec = [-4, -2, 0, 2, 4]
1. print [x*2 for x in vec]
2. print [x for x in vec if x >= 0]
3. print [abs(x) for x in vec]
• [-8, -4, 0, 4, 8]
• [0, 2, 4]
• [4, 2, 0, 2, 4]
More examples
• fruits = [' banana', '
loganberry ', 'passion fruit ']
4. print [fruit.strip() for fruit
in fruits]
5. print [(x, x**2) for x in
range(6)]
More examples
• fruits = [' banana', '
loganberry ', 'passion fruit ']
4. print [fruit.strip() for fruit in
fruits]
5. print [(x, x**2) for x in range(6)]
• ['banana', 'loganberry', 'passion
fruit']
• [(0, 0), (1, 1), (2, 4), (3, 9), (4,
16), (5, 25)]
examples
matrix =
[1,
[5,
[9,
[
2, 3, 4],
6, 7, 8],
10, 11, 12],]
print [row[i] for row in matrix for i in
range(4)]
print [[row[i]] for row in matrix for i in
range(4)]
print [[row[i] for row in matrix] for i in
range(4)]
output
• [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12]
• [[1], [2], [3], [4], [5], [6],
[7], [8], [9], [10], [11], [12]]
• [[1, 5, 9], [2, 6, 10], [3, 7,
11], [4, 8, 12]]
Equivalent to …
transposed = []
for i in range(4):
# the following 3 lines implement
the nested listcomp
transposed_row = []
for row in matrix:
transposed_row.append(row[i])
transposed.append(transposed_row)
Related documents