Introduction To Functional Programming

5,154 views

Published on

A short introduction to functional programming and looping using recursion.

Published in: Technology, Business
1 Comment
9 Likes
Statistics
Notes
No Downloads
Views
Total views
5,154
On SlideShare
0
From Embeds
0
Number of Embeds
232
Actions
Shares
0
Downloads
293
Comments
1
Likes
9
Embeds 0
No embeds

No notes for slide

Introduction To Functional Programming

  1. 1. Intro to Functional Programming <ul><li>Part 1: </li></ul><ul><li>Single-assignment and Recursive Techniques </li></ul>
  2. 2. What is Functional Programming? <ul><li>Functions return values </li></ul><ul><ul><li>Given a set of values in the parameter list, the function can only have one possible result. </li></ul></ul><ul><li>Functions have no side-effects </li></ul><ul><ul><li>Do not modify variables passed to them </li></ul></ul><ul><ul><li>Do not modify any global variable </li></ul></ul><ul><li>Variables only assigned once </li></ul>
  3. 3. What’s the Point? Principle of Least Surprise Principle of Least Surprise <ul><li>All possible inputs to any function are listed in the parameter list - no worries about global state </li></ul><ul><li>Single assignment means that you never have to wonder how a variable got its definition since it is only defined one place in the entire function </li></ul><ul><li>Loops much easier to comprehend and debug </li></ul><ul><li>Simpler execution model makes program proving easier, both for computers and humans (i.e. debugging) </li></ul>Explicitly mention stateless. Might also talk about theoretical statelessness of the web, but also why it isn’t truly stateless.
  4. 4. No assignments! How do you loop? <ul><li>Functional programs are usually heavily recursive </li></ul><ul><li>Looping is either done with a looping construct (such as map , each , select , etc.) or with recursion </li></ul><ul><li>Rather than setting values on each iteration, the loop itself is a function that calls itself recursively </li></ul><ul><li>Each iteration the function simply gets called with new values </li></ul>Need to mention that although you _can_ do recursive algorithms and modify state, that is usually the worst of both worlds.
  5. 5. Recursion Basics <ul><li>Before we talk about looping with recursion, let’s talk about recursion itself </li></ul><ul><li>Recursion is where a function calls itself </li></ul><ul><li>In recursion the goal is to get the data to a smaller version to solve, until it is to a point where the solution is a simple operation -- this is called the base case </li></ul><ul><li>If your recursive function does not have a base case, it will never return . That’s usually considered bad. </li></ul>
  6. 6. Recursion Example: The Factorial Function The Factorial Function <ul><li>The factorial function multiplies a number by each number below it until 1 </li></ul><ul><li>5! (! means factorial) is the same as 5 * 4 * 3 * 2 * 1 </li></ul><ul><li>Here’s the factorial function in ruby: </li></ul>def factorial(number) if number == 1 #Base Case -- compute answer return 1 else #Get us closer to the base case return number * factorial(number - 1) endend Note that we didn’t do ANY assignment in the whole program -- we just passed parameters. Function calls create new variables, so if we think we want to do assignment, in functional programming you usually want to call a function or create a different variable.
  7. 7. Selection Sort Example <ul><li>Two lists: already-sorted values and unsorted values </li></ul><ul><li>First list will start empty </li></ul><ul><li>Each iteration, find the smallest unsorted value and put it at the end of the sorted list </li></ul><ul><li>Base case: unsorted values list is empty - just return the sorted values </li></ul>
  8. 8. Selection Sort Example def select_sort(values) select_sort_loop([], values)enddef select_sort_loop(sorted_values, unsorted_values) if unsorted_values.empty? #BASE CASE! return sorted_values else #FIND SMALLEST VALUE AND ITS INDEX smallest_value_index = find_smallest_value_index(unsorted_values) smallest_value = unsorted_values[smallest_value_index] #CREATE NEW SORTED AND UNSORTED ARRAYS new_sorted_values = add_element(sorted_values, smallest_value) new_unsorted_values = remove_element_index(unsorted_values, smallest_value_index) #LOOP WITH NEW VALUES return select_sort_loop(new_sorted_values, new_unsorted_values) endend select_sort([1,5,23,8,3,5,6,8,34,65,2,5,3])
  9. 9. Selection Sort: Utility Functions Utility Functions def add_element(ary, val) ary.dup.push(val)enddef remove_element_index(ary, idx) idx == 0 ? ary[1..-1] : (idx == (ary.size - 1)) ? ary[1..-2] : ary.slice(0, idx - 1).concat(ary.slice(idx + 1, ary.size - 1))enddef find_smallest_value_index(ary) smallest_idx = 0 ary.each_index do |idx| if ary[idx] < ary[smallest_idx] smallest_idx = idx smallest_val = ary[idx] end end return smallest_idxend
  10. 10. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>In this basic example, it looks like the standard loop is better. But as the loop gets more complicated, knowing exactly what defines your variables makes all the difference between an understandable and a totally incoherent loop.
  11. 11. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>Loop Definition with Parameter Declaration Note that the recursive loop explicitly names its inputs, while the standard loop does not, meaning that to truly know what contributes to the standard loops functionality requires full inspection of the whole loop. Loop Definition
  12. 12. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>Loop Initialization Loop Initialization
  13. 13. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>Loop Invocation An explicit invocation step is not needed for standard loops, as the while statement invokes it implicitly.
  14. 14. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>Loop Condition Loop Condition
  15. 15. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>Loop Body Loop Body
  16. 16. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>Modification of Loop Variables Modification of Loop Variables Note that in the standard loop assignments can occur anywhere, while in recursive loops they only occur by passing new parameters as part of the loop iteration process. Which do you think leads to easier bug detection in large loops? Recursive loops can create new definitions for new variables within the loop, but cannot modify already-assigned variables.
  17. 17. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>Control Variable Modification Control Variable Modification Note that since this is done as a function parameter, no assignment needs to be made. The new value is placed into a new variable (with the same name) in the next function call.
  18. 18. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>Loop Iteration Loop Iteration Not e that since the loop is represented as a function, to get back to the beginning of the loop, all we need to do is a function call. But remember that unless the function call is the last thing you do, the function will return back to the loop!
  19. 19. Basic Recursive Loop <ul><li>A standard loop: i = 0 while(i < 10) { #Do Stuff i = i + 1 } </li></ul><ul><li>A recursive loop: def myloop(i, other, changeable, loop, vars) if i < 10 #Do Stuff return myloop(i + 1, other, changeable, loop, vars) else return whatever #exit loop end end myloop(0, other, changeable, initial, values) </li></ul>Loop Exit Note that the loop exit is explicit in the standard loop but implicit in the recursive loop.
  20. 20. Packaged Looping Constructs <ul><li>These put all of the loop control in a function, and thus out of your hands </li></ul><ul><li>In these, the loop logic is guaranteed reliable, and you are only responsible for the per-iteration logic </li></ul><ul><li>These take a block (or in other languages, a function or lambda expression) which is the per-iteration code </li></ul><ul><li>This usually (but not always) do not carry state from iteration to iteration </li></ul>Should I give an example somewhere?
  21. 21. Packaged Looping Constructs <ul><li>map - takes a list, and for each list member, runs a transformation and returns a new element: [1, 2, 3, 4, 5].map{|x| x * x} => [1, 4, 9, 16, 25] </li></ul><ul><li>each - takes a list, and for each list member, performs an action: [1, 2, 3, 4, 5].each{|x| puts “The value is #{x}”} </li></ul><ul><li>select - filters a list and returns only members for whome the condition is true [1, 2, 3, 4, 5].select{|x| x.remainder(2) == 1} => [1,3,5] </li></ul>Include upto? Somewhere I need to talk about fold and unfold, but that is probably for a different talk.
  22. 22. Functional Looping Advantages <ul><li>For nearly all common cases, packaged looping works best. It is easy to do and easy to get right. </li></ul><ul><li>For more exceptional cases, recursive looping principles offer more structure and more guarantees about your loop state: </li></ul><ul><ul><li>Explicit input parameters </li></ul></ul><ul><ul><li>Single assignment of all variables </li></ul></ul><ul><li>Disadvantages: a little more typing, a lot less familiarity </li></ul>Note that these are the same ones we talked about for FP in general. Also, in general this makes the programs easier to reason about.
  23. 23. General Functional Programming Issues <ul><li>Input/output difficult to deal with </li></ul><ul><li>Requires garbage collection </li></ul><ul><li>Produces more garbage to collect </li></ul><ul><li>Sometimes slower (but usually not by much) </li></ul><ul><li>Some operations are intrinsically stateful - there may be a functional way of doing it but they are cumbersome </li></ul>Mention Monads briefly Do I need to talk about stateful/stateless somewhere?
  24. 24. Practical Tips <ul><li>Use a language (like Ruby!) with plenty of support for functional programming constructs, but that doesn’t force them </li></ul><ul><li>Use packaged loops for iteration whenever you can </li></ul><ul><li>For complicated loops, strongly consider recursive versions </li></ul><ul><li>As much as you can, try to create new variables instead of assigning to existing ones </li></ul><ul><li>You will likely need to modify state at some point, but try to keep it out of as many functions as possible </li></ul>On state modification - might mention how ruby uses ! to mark non-functional versions of traditionally functional functions. When a task requires both computation and state modification, it is often best to separate them into two functions - one to perform the computation and one to actually perform the state change (usually with the state-change function calling the computational function, but not always).
  25. 25. References <ul><li>Mastering Recursive Programming http://www-128.ibm.com/developerworks/linux/library/l-recurs.html </li></ul><ul><li>Introduction to Haskell (includes recursive techniques) http://www-128.ibm.com/developerworks/edu/os-dw-linuxhask-i.html </li></ul><ul><li>Recursion Examples http://www.juniata.edu/faculty/kruse/cs2java/recursion2.htm </li></ul><ul><li>More Recursion Examples http://www.sparknotes.com/cs/recursion/examples/ </li></ul>

×