Download presentation
Presentation is loading. Please wait.
Published byMartina Leonard Modified over 8 years ago
1
Introduction to Concepts in Functional Programming CS16: Introduction to Data Structures & Algorithms Thursday, April 9, 2015 1
2
Outline State Functions as Building Blocks Higher order Functions Map Reduce Thursday, April 9, 2015 2
3
What is Functional Programming? Functional programming is a style of programming that is fairly different from what you’ve done in CS15/CS16 Examples of functional languages: Haskell, Clojure, Common Lisp, OCaml Important features that we’ll discuss: Programs are built entirely of functions Computations do not change program state Thursday, April 9, 2015 3
4
Functions In math: f(x) = x + 1 In python: def f(x): return x + 1 Every input maps to exactly one output A value is always returned Thursday, April 9, 2015 4
5
What is State? State is defined by all stored information to which a program has access at any given time Mutable data is data that can be changed after creation. Mutating data changes program state. Immutable data cannot be changed after creation. A language with only immutable data can never change program’s state. Thursday, April 9, 2015 5
6
State Continued Some paradigms (like the ones you’ve seen in CS15/16) operate by manipulating program state Some familiar examples: Mutator methods Methods/functions that don’t return anything Loops that mutate local variables (such as the incrementation variable) Thursday, April 9, 2015 6
7
State Continued This also means that the same function can behave on the data in an entirely different way depending on the program state Example: Simulation of driving behavior based on the the color of a stoplight Thursday, April 9, 2015 7
8
Stateful Program Example light_color = “RED” def change_light(): //Mutates light_color based on it’s current value if light_color is “RED”: light_color = “GREEN” if light_color is “YELLOW”: light_color = “RED” if light_color is “GREEN”: light_color = “YELLOW” //Note that this does not have to return anything to impact the program! def drive(car): if light_color is “RED”: car.stop() if light_color is “YELLOW”: car.slow_down() if light_color is “GREEN”: car.move_forward() Thursday, April 9, 2015 8 //This function behaves differently based on the value of light_color
9
Functional Programming and State Pure functional languages avoid changing state, and all data is immutable What does this imply? Functions are deterministic: the same input will always give the same output Programs do not contain side effects (see upcoming example) Order of execution is no longer important Functions are easier to reuse elsewhere Thursday, April 9, 2015 9
10
Mutable vs Immutable State Example Imagine you have these 2 programs: Will they produce the same result if they are allowed to change state? What if all state is immutable? Thursday, April 9, 2015 10 Program 1Program 2 a = f(x) b = g(y) return h(a, b) b = g(y) a = f(x) return h(a, b)
11
Mutable vs Immutable State Example Continued Imagine you have these 2 programs: Mutable State: These are not guaranteed to be the same because the first function call might change state, resulting in different behavior of the second function call. This is an example of a side effect. Immutable State: These will ALWAYS produce the same result Thursday, April 9, 2015 11 Program 1Program 2 a = f(x) b = g(y) return h(a, b) b = g(y) a = f(x) return h(a, b)
12
State and Loops Another place you have commonly seen mutable state is in for loops and while loops. Without mutable state, traditional for loops and while loops cannot exist! Many functional languages do not have loop constructs. Instead, they make use of recursion. Thursday, April 9, 2015 12
13
Why No Loops? Loops often depend on mutable variables. def max(input_list): max = -infinity for i from 0 to len(input_list): if input_list[i] > max: max = input_list[i] return max Where is state being mutated? Thursday, April 9, 2015 13
14
Why No Loops Continued def max(input_list): max = -infinity for i from 0 to len(input_list): //changing ‘i’ if input_list[i] > max: max = input_list[i] //changing ‘max’ return max This will not work if all variables are immutable In a functional language, you would have to write this without mutation. How…? Thursday, April 9, 2015 14
15
Replacing Iteration with Recursion The version on the right would work in a pure functional language. The version on the left would not. 15 Iterative Max Function (With Mutation)Recursive Max Function (Without Mutation) def max(input_list): max = -infinity for i from 0 to len(input_list): if input_list[i] > max: max = input_list[i] return max def max(input_list): return max_helper(input_list, -infinity) def max_helper(input_list, max): if len(input_list) == 0: return max if input_list[0]> max: return max_helper(input_list[1:], input_list[0]) return max_helper(input_list[1:], max) Thursday, April 9, 2015
16
First Class Functions In the functional paradigm, functions are first class i.e. they can be passed around and returned like any other data As an example: def add_one(x): return x + 1 def apply_function_to_five(f): return f(5) print apply_function_to_five(add_one) >> 6 Thursday, April 9, 2015 16
17
First Class Functions Let’s look more closely at our add_one function: def add_one(x): return x + 1 What is actually happening here? We’re simply binding a function to the identifier add_one In python (which supports aspects of functional programming), this is 100% equivalent to: add_one = lambda x: x+1 Thursday, April 9, 2015 17 More on this syntax soon!
18
First Class Functions Now our function looks much more similar to the way we usually express bound data Examples: a = 23 //binding a number b = “David” //binding a string c = True //binding a boolean d = lambda x: x+1 //binding a function Thursday, April 9, 2015 18
19
Anonymous Functions Numbers, booleans, strings etc. do not have to be bound in a program. Neither do functions! Anonymous Function: a function that is not bound to an identifier Python Examples: lambda x: x+1 // Input: a number k // Output: a function that increments k by a number def increment_by_k_function(k): return lambda x: return x + k Thursday, April 9, 2015 19
20
Function Syntax Overview Thursday, April 9, 2015 20 MathBound Python Function Anonymous Function in Python f(x) = x + 1 def f(x): return x + 1 or f = lambda x: x+1 lambda x: x + 1
21
Higher Order Functions A higher order function is one that takes in one or more functions as input or outputs a function. You’ve already seen functions that take other functions as input! Example from earlier in these slides: print apply_function_to_five(add_one) >> 6 Thursday, April 9, 2015 21
22
Higher Order Functions But what does it look like to output a function? >> def add_me_func(x): return lambda y: x + y //returns an unsatisfied function // 1 is the value passed in for ‘x’ in a >> add_one = add_me_func(1) >> print add_one // this prints the value of add_one, which is a function object returned by calling add_me_func(1) at 0x123e410> // 5 corresponds to the parameter ‘y’ in the function returned by add_me_func(1) which is lambda y: 1 + y >> print add_one(5) 6 Thursday, April 9, 2015 22
23
Higher Order Functions You can even do both in one function! >> def satisfy_first_arg(func, x): return lambda y: func(x,y) //satisfies one arg >> def add(x,y): return x + y // ‘add’ corresponds to the argument ‘func’ and 1 corresponds to the argument ‘x’ in satisfy_first_arg(func,x) >> add_one = satisfy_first_arg(add, 1) // add_one represents the function lambda y: add(1, y) at 0x123e410> // this evaluates and prints lambda 7: add(1,7) >> print add_one(7) 8 Thursday, April 9, 2015 23
24
Map Map is a higher order function that applies a function to all elements in a list, and returns a new list. Inputs: f - a function x - a collection of elements Output: a collection of elements, with f applied to each of the elements of x Thursday, April 9, 2015 24
25
Map Thursday, April 9, 2015 25 11 24 16 -5 34 4 66 9 22 14 -7 32 2 f(x) = x - 2 64 In python: map(lambda x: x-2, [11,24,16,-5,34,4,66])
26
Reduce (also called Fold) Reduce is a bit trickier to wrap your head around General idea: It reduces a whole list to a return value using some binary function to combine the elements Inputs: f - binary function x - list of elements acc - accumulator (what will be updated and returned) Outputs y - the value of f sequentially applied and tracked in acc Thursday, April 9, 2015 26
27
Reduce Reduce is roughly equivalent to this python function: def reduce (binary_function, data_structure, accumulator): for x in data_structure: accumulator = binary_function(accumulator, x) return accumulator Thursday, April 9, 2015 27
28
Reduce Example f = lambda x,y: x + y reduce(f, [1,2], 0) Thursday, April 9, 2015 28 Binary function Input Collection Accumulator
29
Reduce f = lambda x,y: x + y reduce(f, [1,2], 0) Thursday, April 9, 2015 29 ((0+1)+2) = reduce(f,[1,2],0)= Current Accumulator
30
Reduce f = lambda x,y: x + y reduce(f, [1,2], 0) Thursday, April 9, 2015 30 ((0+1)+2) = (1+2) = reduce(f,[1,2],0)= reduce(f,[2],1)= Current Accumulator
31
Reduce f = lambda x,y: x + y reduce(f, [1,2], 0) Thursday, April 9, 2015 31 ((0+1)+2) = (1+2) = 3 reduce(f,[1,2],0)= reduce(f,[2],1)= 3 Final Accumulator/Return Value
32
32 Reduce f = lambda x,y: x*y reduce(f, [1,2,3,4,5], 1)
33
Reduce f = lambda x,y: x*y reduce(f, [1,2,3,4,5], 1) Thursday, April 9, 2015 33 (((((1*1)*2)*3)*4)*5) = ((((1*2)*3)*4)*5) = (((2*3)*4)*5) = reduce(f,[1,2,3,4,5],1) = reduce(f,[2,3,4,5],1)= reduce(f,[3,4,5],2)= Current Accumulator
34
Reduce f = lambda x,y: x*y reduce(f, [1,2,3,4,5], 1) Thursday, April 9, 2015 34 (((((1*1)*2)*3)*4)*5) = ((((1*2)*3)*4)*5) = (((2*3)*4)*5) = ((6*4)*5) = reduce(f,[1,2,3,4,5],1) = reduce(f,[2,3,4,5],1)= reduce(f,[3,4,5],2)= reduce(f,[4,5],6)= Current Accumulator
35
Reduce f = lambda x,y: x*y reduce(f, [1,2,3,4,5], 1) Thursday, April 9, 2015 35 (((((1*1)*2)*3)*4)*5) = ((((1*2)*3)*4)*5) = (((2*3)*4)*5) = ((6*4)*5) = (24*5) = reduce(f,[1,2,3,4,5],1) = reduce(f,[2,3,4,5],1)= reduce(f,[3,4,5],2)= reduce(f,[4,5],6)= reduce(f,[5],24)= Current Accumulator
36
Reduce f = lambda x,y: x*y reduce(f, [1,2,3,4,5], 1) Thursday, April 9, 2015 36 (((((1*1)*2)*3)*4)*5) = ((((1*2)*3)*4)*5) = (((2*3)*4)*5) = ((6*4)*5) = (24*5) = 120 reduce(f,[1,2,3,4,5],1) = reduce(f,[2,3,4,5],1)= reduce(f,[3,4,5],2)= reduce(f,[4,5],6)= reduce(f,[5],24)= 120 Final Accumulator/Return Value
37
Reduce The accumulator doesn’t always have to be an integer, and reduce doesn’t always have to reduce a list into a single number Example: removing consecutive duplicates, the accumulator will be a list! def compress(my_list): f = lambda acc, e: acc + [e] if acc[-1] is not e else acc return reduce(f, my_list, [my_list[0]]) Thursday, April 9, 2015 37
38
Reduce The accumulator doesn’t always have to be an integer, and reduce doesn’t always have to reduce a list into a single number Example: removing consecutive duplicates, the accumulator will be a list! def compress(my_list): f = lambda acc, e: acc + [e] if acc[-1] is not e else acc return reduce(f, my_list, [my_list[0]]) Thursday, April 9, 2015 38 Note: This way of writing if/else is called a ternary operator
39
Higher Order Functions With higher order functions, we can build abstractions for many constructs and make programs much more concise. Let’s revisit the recursive max function we saw earlier: Thursday, April 9, 2015 39 Original Recursive ExampleRevised with Higher Order Functions def max(input_list): return max_helper(input_list, -infinity) def max_helper(input_list, max): if len(input_list) == 0: return max if input_list[0]> max: return max_helper(input_list[1:], input_list[0]) return max_helper(input_list[1:], max) def max(input_list): find_max = lambda acc, elem: elem if elem > acc else acc return reduce(find_max, input_list, -infinity)
40
Building Programs With all of this information, we can start to see how programs can be built in a functional style Programs can be thought of as one giant function composition f(g(...h(x)...)). Pretty Cool! In pure functional languages, programs can not be expressed as a series of instructions because this type of programming requires mutation. Thursday, April 9, 2015 40
41
Advantages and Disadvantages of Functional Programming Thursday, April 9, 2015 41 AdvantagesDisadvantages
42
Advantages and Disadvantages of Functional Programming It’s difficult to pick out advantages vs disadvantages because FP is simply better suited for certain problems, but here are a few: Thursday, April 9, 2015 42 AdvantagesDisadvantages ●Programs are deterministic ●Code is often elegant and concise because of the expressive abstractions ●Code is easy to run concurrently because everything is immutable ●Learning functional programming teaches you to think about problems in a different way, which ultimately makes you a better problem solver ●Programs are deterministic ●Potential performance losses because of the amount of garbage collection – takes up more memory, and takes longer to create new variables when you want to fake “mutate” them ●I/O is difficult because it requires interaction with state ●It’s very different from imperative programming, so many programmers find it difficult to learn
43
Functional Programming Practice Thursday, April 9, 2015 43 Syntax Examples: lambda x: x + 1 map(lambda x: x-2, [11,24,16,-5,34,4,66]) reduce(f, [1,2], 0)
44
Functional Programming Practice Thursday, April 9, 2015 44 Problem: Write an anonymous function that raises a single argument n to the nth power
45
Functional Programming Practice Thursday, April 9, 2015 45 Solution: lambda n: n**n
46
Functional Programming Practice Thursday, April 9, 2015 46 Problem: Write a line of code that applies the function you wrote in part 1 to an input list
47
Functional Programming Practice Thursday, April 9, 2015 47 Solution: map(lambda n: n**n, list)
48
Functional Programming Practice Thursday, April 9, 2015 48 Problem: Write an anonymous function that takes in a single argument n and returns a function that consumes no arguments and returns n
49
Functional Programming Practice Thursday, April 9, 2015 49 Solution: lambda n: lambda: n
50
Functional Programming Practice Thursday, April 9, 2015 50 Problem: Write a line of code that applies the function you wrote in part 3 to an input list. This should give you a list of functions. Next, write a line of code that takes in that list of functions and turns it back into the original list.
51
Functional Programming Practice Thursday, April 9, 2015 51 Solution: Part 1: function_list = map(lambda n: lambda: n, list) Part 2: map(lambda n: n(), function_list)
52
Functional Programming Practice Thursday, April 9, 2015 52 Problem: Remove odd numbers from a list using reduce
53
Functional Programming Practice Thursday, April 9, 2015 53 Solution: def remove_odds(my_list): return reduce(lambda x, y: x + [y] if y%2 is 0 else x, my_list, [])
54
Higher Order Functions There are a number of commonly-used higher- order functions We only got to talk about map and reduce. But there are many more! Thursday, April 9, 2015 54
55
Higher Order Functions f- function, may have to be of certain arity x - collection of elements y - collection of elements filter(f,x) returns a list of only those in x that make f true – f is a function that evaluates to true or false based on the input zipWith(f,x,y) takes in 2 lists of the same length and passes elements with the same index into a binary function f to return a single list find(f, x) returns 1st element of x where f returns true Thursday, April 9, 2015 55
56
Functional Programming Example: Hash function def my_hash(mul, key, size): sum = 0 for i in range(len(mul)): sum += mul[i] * key[i] return sum % size Thursday, April 9, 2015 56 def my_hash(mul, key, size): return reduce(plus,zipWith(mul,key,size),0) % size Versus:
57
57 Questions ?
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.