Intro to Functional Programming

Part 1: Single-assignment and Recursive Techniques

What is Functional Programming?

Functions return values Given a set of values in the parameter list, the function can only have one possible result.

Functions have no side-effects

Do not modify variables passed to them Do not modify any global variable

Variables only assigned once

Principle of Least Surprise All possible inputs to any function are listed in Principlelist - no worries about global of Least the parameter state Surprise

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 Loops much easier to comprehend and debug Simpler execution model makes program proving easier, both for computers and Explicitly mention stateless. Might also talk about theoretical statelessness humans (i.e. debugging) truly stateless. of the web, but also why it isn’t

No assignments! How do you loop? Functional programs are usually heavily

Functional programs are usually heavily recursive

Looping is either done with a looping construct (such as map, each, select, etc.) or with recursion

Rather than setting values on each iteration, the loop itself is a function that calls itself recursively Each iteration the function simply gets called with new values
Need to mention that although you _can_ do recursive algorithms and modify state, that is usually the worst of both worlds.

Recursion Basics

Before we talk about looping with recursion, let’s talk about recursion itself Recursion is where a function calls itself 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 If your recursive function does not have a base case, it will never return. That’s usually considered bad.

Recursion Example: The Factorial Function The Factorial Function by The factorial function multiplies a number

each number below it until 1

5! (! means factorial) is the same as 5 * 4 * 3 * 2*1

Here’s the factorial function in ruby:

mpute answer    return 1        else            #Get us closer to the bas mpute answer    return 1        else            #Get us closer to the ba
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.

Selection Sort Example

Two lists: already-sorted values and unsorted values First list will start empty

Each iteration, find the smallest unsorted value and put it at the end of the sorted list Base case: unsorted values list is empty - just return the sorted values

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])

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

Basic Recursive Loop
A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

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.

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)

Basic Recursive Loop
A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

Loop Definition 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.

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)

Loop Definition with Parameter Declaration

Basic Recursive Loop
A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

Loop Initialization

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)

Loop Initialization

Basic Recursive Loop
A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

An explicit invocation step is not needed for standard loops, as the while statement invokes it implicitly.

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)

Loop Invocation

Basic Recursive Loop
A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

Loop Condition

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)

Loop Condition

Basic Recursive Loop
A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

Loop Body

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)

Loop Body

Basic Recursive Loop
A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

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?

Modification of Loop Variables

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)

Modification of Loop Variables
Recursive loops can create new definitions for new assigned variables.

variables within the loop, but cannot modify already-

Basic Recursive Loop
A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

Control Variable Modification

A recursive loop:

  def myloop(i, other, changeable, loop, vars)     if i < 10       #Do Stuff

      return myloop(i + 1, other, changeable, loop, vars) done as a function     else       return whatever  #exit loop parameter, no     end   end assignment needs to be   myloop(0, other, changeable, initial, values)

Control Variable that since this is Modification Note

made. The new value is placed into a new variable (with the same name) in the next

Basic Recursive Loop
Not e that since the loop

A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

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!

Loop Iteration Loop Iteration

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)

Basic Recursive Loop
A standard loop:
  i = 0   while(i < 10) {     #Do Stuff     i = i + 1   }

Note that the loop exit is explicit in the standard loop but implicit in the recursive loop.

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)

Loop Exit

Packaged Looping Constructs These put all of the loop control in a function,
Should I give an example somewhere?

These put all of the loop control in a function, and thus out of your hands In these, the loop logic is guaranteed reliable, and you are only responsible for the periteration logic

These take a block (or in other languages, a function or lambda expression) which is the per-iteration code This usually (but not always) do not carry state from iteration to iteration

Packaged Looping Constructs

Include upto?

Somewhere I need to talk about fold and unfold, but that is probably for a different talk.

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]

each - takes a list, and for each list member, performs an action:
[1, 2, 3, 4, 5].each{|x| puts “The value is #{x}”}

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]

Functional Looping Advantages cases, packaged looping For nearly all common

works best. It is easy to do and easy to get right.

For more exceptional cases, recursive looping principles offer more structure and more Note that are the guarantees about your loop state: thesetalked same ones we

Explicit input parameters

about for FP in general. Also, in general this makes the programs easier to reason about.

Single assignment of all variables

Disadvantages: a little more typing, a lot less familiarity

General Functional Programming Issues

Mention Input/output difficult to deal withMonads briefly

Requires garbage collection

Produces more garbage to collect Sometimes slower (but usually not by much) Some operations are intrinsically stateful there may be a functional way of doing it but they are cumbersome Do I need to talk about stateful/stateless
somewhere?

Practical Tips

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 statechange function calling the computational function, but not always).

Use a language (like Ruby!) with plenty of support for functional programming constructs, but that doesn’t force them Use packaged loops for iteration whenever you can

For complicated loops, strongly consider recursive versions As much as you can, try to create new variables instead of assigning to existing ones You will likely need to modify state at some point, but try to keep it out of as many functions as possible

References

Mastering Recursive Programming http://www-128.ibm.com/developerworks/linux/library/l-recurs.html Introduction to Haskell (includes recursive techniques) http://www-128.ibm.com/developerworks/edu/os-dw-linuxhask-i.html Recursion Examples http://www.juniata.edu/faculty/kruse/cs2java/recursion2.htm More Recursion Examples http://www.sparknotes.com/cs/recursion/examples/