### Lightning Talkpaufler.net@gmail.com

Not so much a How, as a Why.

## My Stack

A forward looking statement, at best.

• Linux
• emacs
• Lisp
• C
• Python
• IDE: Eclipse with PyDev

I know.
I don't know.
Has a Functional basis.

## Bona Fides

Be impressed.
Be very impressed. /s

Haskell for 3 months in a single problem domain (Project Euler).

No CS, BS, MS, or Phd
Not a PL guy (Project Language)
No Category Theory
None of Church's Lambda Calculus

So, may be a case of the blind leading the blind.
Or the blissfully ignorant demonstrating their stupidity.
I'll let you decide.

Aspire to be stupid.
Dare to be wrong.

## Functional Programming is Not a Look or a Feel

No matter how you may feel about that.

``````
#Find Squares of a List
a = [1, 2, 3, 4]

def f(n):
'''Return square of n.'''
return pow(n, 2)

x = []
for v in a:
x.append(f(v))

y = [f(b) for b in a]

z = map(f, a)

print x     #[1, 4, 9, 16]
print y     #[1, 4, 9, 16]
print z     #[1, 4, 9, 16]

``````

`f(n)` is as functional as it gets.
As to `x`, `y`, & `z`, all three get the job done.
They are all Functionally equivalent.

``````
def mess(x):
x = int(x)
print 'mess running: %d' % x
x = x * x
print 'mess returning: %d' % x
if x:
return x
else:
return None

print map(mess, a)
#[1, 4, 9, 16]

``````

• The above code sucks.
• `mess` is NOT functional.
• Reassignment to x.
• Returns multiple types.
• int
• None
• Has side effects
• print
But we can abstract it and not worry about any of that.

``````
g = mess
print map(g, a)
#[1, 4, 9, 16]

for_loop = map
print for_loop(g, a)
#[1, 4, 9, 16]

``````

The difference between `f(x)` or `g(x)` & `map(f, x)` or `for_loop(g, a)`is purely aesthetic.

Functional Programming is not an aesthetic cult (an ascetic cult maybe, but that's a talk for a different day).

# A Bold Claim ImmutabilityIs The Heart of Functional Programming

``````
#Functional           #Non-Functional
x = 1                 x = 1
y = x + 1             x = x + 1

z = map(f, x)         x = map(f, x)

``````

In Functional Programming, re-assignment of variables is not allowed.
That's it.
That's the secret.
That's Functional Programming in a nutshell.

## But It's All a Lie

Even in Functional Programming things are mutated all the time.
• Computer Memory is Mutable
• Registers are continually reassigned at the chip level.
• Haskell is implemented in C.
• Hard to believe they didn't use loops.
• A loop requires: i++

Perhaps even more damning, Haskell's Hello World is procedural.
``````
main :: IO ()
main = do
putStrLn "Hello World"

``````

IO () is a monad (more on this later).
`do` is a procedural escape (i.e. it's not Functional).
So at the point of being practical, Haskell stops being Functional.

## sum(range(10))Functional vs Proceedural

More things change on the right than the left.

run_tot => sum(items) => sum(range(10)) => sum([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) => 45

`run_tot` reduces to (i.e. ~ points towards ) the same thing all the time.
So, in a certain sense, what run_tot is never changes.

It's not that there are fewer moving parts.
It's that the parts that are there don't move.

## So Why Care? What Does Immutability Buy Us?

• Easy to prove correctness.
• Mathematically convenient.
• Do you care?
• Easy to prove means easier to reason.
• That means fewer bugs.
• No side effects.
• Concurancy
• No race conditions.
• Lazy evaluation.

## Functional Programming Run Through

More like a drive by,
worked from the bottom up.

``````
x = my_first_thought(data_1)
y = something_better()
z = what_should_have_come_first(data_2)

solution_set = f(y, z)

#The Output Requested
print solution_set

``````
• Lazy Evaluation
• `x` is never used.
• So, `my_first_thought()` never used.
• And no side effects.
• Thus, neither need be evaluated.
• Easy to Reason
• `y` has no inputs, so its a static data set.
• ex: `range(10, 110, 10)`
• `f(y, z)` has no side effects (by definition).
• So, all we have to do is examine its return values.
• Same for `what_should_have_come_first(data_2)`.
• Thus, limited scope for errors.
• If a function is valid, that function is always valid.
• Concurancy
• `x`, `y`, & `z` share no inputs
• Share no dependencies.
• Separate evaluation
• Different cores OK.

## The Anti-PatternUn-Pythonic Code

``````
class powers(int):
def __new__(self, num):
return int.__new__(self, num)
def __init__(self, num):
self.p1 = pow(num, 1)
self.p2 = pow(num, 2)
self.p3 = pow(num, 3)
return self + r_int
def state(self):
print 'Base: %d, Square: %d, Cube: %d' % (
self.p1, self.p2, self.p3)

p = powers(3)
p.state()
#Base: 3, Square: 9, Cube: 27
p.p1 = 10
p.state()
#Base: 10, Square: 9, Cube: 27

``````

State changes aren't always updated (or in time).

## The Patterna.k.a.More Functional Code

### Simple Steps to Better Code

Single return values.
Separation of side effects.

``````

#Return a single value type:

return x + y                        if x and y:
return x + y
else:
return 'Need two ints'

#Isolate side effects

def updater(p_num):                 def update_pr(p_num):
p_num.p2 = pow(num, 2)              p_num.p2 = pow(num, 2)
p_num.p3 = pow(num, 3)              p_num.p3 = pow(num, 3)
return (p_num.p2, p_num.p3)
t = (p_num.p2, p_num.p3)

``````

### Filters

Separating the wheat from the chaff.

``````
def long_form_of_even(n):
test = n % 2 == 0
if test:
return True
else:
return False

def even(n):
return n % 2 == 0

to_ten = range(10)
#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

even_to_ten = [t for t in to_ten if even(t)]
#[0, 2, 4, 6, 8]

even_to_ten = filter(even, to_ten)
#[0, 2, 4, 6, 8]

from itertools import compress
mask = [even(t) for t in to_ten]
#[True, False, True, False, True,
False, True, False, True, False]
#[0, 2, 4, 6, 8]

``````

### Lists

Some folks take notes, I make lists.

``````
#Simple Map (list to list)

x = range(10)
map_1 = map(lambda x: x*x, x)
map_2 = [a*a for a in x]

#x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#map_1 = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
#map_2 = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

#Simple Reduce (list to scalar)

reduce_1 = sum(x)
#x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#reduce_1 = 45

reduce_2 = 0
while x:
reduce_2 += x.pop()
#x = []
#reduce_2 = 45

``````

Map takes a list, returns a list.
Reduce takes a list, returns a scalar.

The real 'Hello World' of the Haskell world.

or inverted wrappers if you want to get technical about it.

### Simple Wrapper

``````
def pre_post_pass_through(func):
def whatever():
print 'pre-process'
func()
print 'post-process'
return whatever

@pre_post_pass_through
def base_function():
print '\tMain Process'

base_function()

#pre-process
#	Main Process
#post-process

``````

### Round Trip

Being a simple little example...

``````
def water_state(Celsius):
'''Returns a string indicating water phase
at provided temperature in Celsius.'''
if Celsius <= 0:
t = 'solid'
elif Celsius < 100:
t = 'liquid'
else:
t = 'gaseous'
return t

def warmer(Celsius):
'''Adds 10 degrees to Celsius, making it warmer.'''
return 10.0 + Celsius

def report(Celsius):
'''Returns text string reporting phase/temp.'''
return 'Water is {} at {:.2f}C'.format(
water_state(Celsius), Celsius)

def Celsius_wrapper(func):
'''Round trip conversion from Fahrenheit to Celsius and back,
executing wrapped function using units in Celsius.'''
def wrapper(Fahrenheit):

#conversion in (pre-process)
Celsius = (Fahrenheit - 32.0) * 5.0/9.0
print 'Fahrenheit in: ', round(Fahrenheit, 2)
print report(Celsius)

#Execution of wrapped function
Celsius = func(Celsius)
print '\tfunction call'

#conversion out (post-process)
Fahrenheit = Celsius * 9.0 /5.0 + 32.0
print report(Celsius)
print 'Fahrenheit out: ', round(Fahrenheit, 2)

return Fahrenheit
return wrapper

@Celsius_wrapper
def warmer_Fahrenheit(Fahrenheit):
return warmer(Fahrenheit)

print 'Returned Value: %.2f' % warmer_Fahrenheit(Fahrenheit=25)
#Fahrenheit in:  25.0
#Water is solid at -3.89C
#	function call
#Water is liquid at 6.11C
#Fahrenheit out:  43.0
#Returned Value: 43.00

print 'Returned Value: %.2f' % warmer_Fahrenheit(Fahrenheit=25)
#Fahrenheit in:  25.0
#Water is solid at -3.89C
#	function call
#Water is liquid at 6.11C
#Fahrenheit out:  43.0
#Returned Value: 43.00

``````

Functional is the exception
``````
@functional_programming
def python_code():
do_stuff_functionally_for_a_change()

``````

Procedural is the exception
``````
@procedural_programming
do_stuff_procedurally_for_a_change()

``````

Monads are the escape hatch to the real world in functional programming.

## CurryingClosuresand otherCool Stuff

### Currying

Is the process of partially pre-filling a function.

``````
#Pre-filling with a function
curry_func = lambda y: map(lambda x: x*x, y)
print curry_func(range(5))
#[0, 1, 4, 9, 16]

#Pre-filling with data
curry_data = lambda y: map(y, range(5))
print curry_data(lambda x : x*x)
#[0, 1, 4, 9, 16]

``````

Classes are functions attached to data.
Closures are data attached to functions.

### In the EndEnlightenment

You know, because I promised some cool stuff at the end, there.

www.paufler.net

paufler.net@gmail.com