Lately i've been using Python as it is widely used on any programming related courses from Udacity and Coursera. This blog will be dedicated to the field of functional programming.
A nice example to get started is the Fibonacci sequence which you can easily implement recursively or iteratively. We will focus on recursive solutions and fix any performance issues along the way.
A recursive functional style implementation:
I use CodePad to run the python code which gives following output (which can of course vary).
If you try to execute fibonacci(40) you will already run into a timeout. So we need a way to temporary store calculated values so we don't need to recalculate them over and over again. Python offers a nice way to accomplish this.
As you can see the same invocation now only makes 32 function calls and has become very fast.
A recursive functional style implementation:
def fibonacci(n):
if n == 0:
return 0
if n == 1:
return 1
else:
return fibonacci(n-2) + fibonacci(n-1)
import cProfile
cProfile.run('print fibonacci(10)')
I use CodePad to run the python code which gives following output (which can of course vary).
55
179 function calls (3 primitive calls) in 0.127 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 0.127 0.127 <string>:1(<module>)
177/1 0.126 0.001 0.126 0.126 t.py:1(fibonacci)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
If you try to execute fibonacci(40) you will already run into a timeout. So we need a way to temporary store calculated values so we don't need to recalculate them over and over again. Python offers a nice way to accomplish this.
def memoize(f):
"""Decorator that caches the return value for each call to f(args)"""
cache = {} # create a dictionary
def _f(*args):
try:
#try to retrieve value from cache
return cache[args]
except KeyError:
#value was not found se we first cache it and return it
cache[args] = result = f(*args)
return result
except TypeError:
#Some values can't be used as keys so we have to calculate the result
return f(args)
return _f
@memoize
def fibonacci(n):
if n == 0:
return 0
if n == 1:
return 1
else:
return fibonacci(n-2) + fibonacci(n-1)
import cProfile
cProfile.run('print fibonacci(10)')
As you can see the same invocation now only makes 32 function calls and has become very fast.
55
32 function calls (4 primitive calls) in 0.007 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 0.007 0.007 <string>:1(<module>)
19/1 0.003 0.000 0.006 0.006 t.py:13(_f)
11/1 0.003 0.000 0.006 0.006 t.py:26(fibonacci)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
No comments:
Post a Comment