You are on page 1of 25

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
Principle

of Least
All possible inputs to any function are listed in
the parameter list - no worries about global
Surprise
state
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
humans (i.e. debugging)
about theoretical statelessness of the web, but
also why it isn’t truly stateless.
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
Need to mention that

Each iteration the function simply gets called


although you _can_ do
recursive algorithms and
modify state, that is
with new values
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
The factorial Function
function multiplies a number by
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
In this basic example, it looks like
A standard loop: the standard loop is better. But as
  i = 0
  while(i < 10) { the loop gets more complicated,
    #Do Stuff
knowing exactly what defines your
    i = i + 1 variables makes all the difference
  }
between an understandable and a
A recursive loop: totally incoherent 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
Loop
A standard loop: Definition
Note that the recursive loop explicitly
  i = 0
  while(i < 10) {
    #Do Stuff
names its inputs, while the standard
loop does not, meaning that to truly
    i = i + 1
  } know what contributes to the standard
loops functionality requires full
A recursive loop: inspection of the whole 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
Loop Definition with
  end
Parameter Declaration
  myloop(0, other, changeable, initial, values)
Basic Recursive Loop
A standard loop:
  i = 0
  while(i < 10) {
Loop Initialization
    #Do Stuff

    i = i + 1
  }

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
Loop Initialization
  myloop(0, other, changeable, initial, values)
Basic Recursive Loop
An explicit invocation
A standard loop: step is not needed for
  i = 0
  while(i < 10) { standard loops, as the
    #Do Stuff
while statement invokes
    i = i + 1 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 Loop Invocation
  myloop(0, other, changeable, initial, values)
Basic Recursive Loop
A standard loop:
  i = 0
  while(i < 10) {
    #Do Stuff
Loop Condition
    i = i + 1
  }

A recursive loop:
  def myloop(i, other, changeable, loop, vars)
    if i < 10
      #Do Stuff
Loop Condition
      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 Loop Body
    i = i + 1
  }

A recursive loop:
  def myloop(i, other, changeable, loop, vars)
    if i < 10
      #Do Stuff
Loop Body
      return myloop(i + 1, other, changeable, loop, vars)
    else
      return whatever  #exit loop
    end
  end

  myloop(0, other, changeable, initial, values)
Basic Recursive Loop Note that in the standard loop
assignments can occur anywhere, while
in recursive loops they only occur by
A standard loop: passing new parameters as part of the
  i = 0
  while(i < 10) {
loop iteration process. Which do you
    #Do Stuff think leads to easier bug detection in
    i = i + 1 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 Modification of Loop Variables
  myloop(0, other, changeable, initial, values)
Recursive loops can create new definitions for new
variables within the loop, but cannot modify already-
assigned variables.
Basic Recursive Loop
A standard loop:
  i = 0
  while(i < 10) {
    #Do Stuff Control Variable
    i = i + 1
  }
Modification

A recursive loop:
  def myloop(i, other, changeable, loop, vars)
    if i < 10
      #Do Stuff Control Variable Modification
Note that since this is
      return myloop(i + 1, other, changeable, loop, vars)
    else done as a function
      return whatever  #exit loop parameter, no
    end
  end assignment needs to be
  myloop(0, other, changeable, initial, values) 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: is represented as a


  i = 0 function, to get back to
  while(i < 10) {
    #Do Stuff the beginning of the loop,
all we need to do is a
    i = i + 1
  }
Loop Iteration function call. But
remember that unless the
A recursive loop: function call is the last
  def myloop(i, other, changeable, loop, vars)
    if i < 10 thing you do, the function
      #Do Stuff
Loop Iteration will return back to the
      return myloop(i + 1, other, changeable, loop, vars)
    else loop!
      return whatever  #exit loop
    end
  end

  myloop(0, other, changeable, initial, values)
Basic Recursive Loop
A standard loop: Note that the loop exit is
  i = 0
  while(i < 10) {
explicit in the standard
    #Do Stuff loop but implicit in the
    i = i + 1 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 Loop Exit
  myloop(0, other, changeable, initial, values)
Packaged Looping Should I give an example

Constructs somewhere?


These put all of the loop control in a function,
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 per-
iteration 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 Include upto?

Constructs
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

For nearly all common cases, packaged looping
works best. It is easy to do and easy to get
right.
For more exceptional cases, recursive looping
principles offer more structure and more
guarantees about your loop state:
Note that these are the
same ones we talked
about for FP in general.

Explicit input parameters 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

Input/output difficult to deal with
Mention Monads 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?
mark non-functional versions of traditionally functional
functions.

Practical Tips 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-

Use a language (like Ruby!) with plenty of
change function calling the computational function, but not
always).

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/

You might also like