Hello, Functional Programming

 

Changing the world only when we have to

 

I:Boss

Supanat Potiwarakorn @ CP 39

Scala

an object-functional language

You can borrow the concept and apply to almost every language

Why should I care about it?

easier to reason about your code

easier to test

easier to do parallel programming

So what is Functional Programming?

Functional Programming is declarative

THE STYLE

f(x) = x + 5
f(x)=x+5f(x) = x + 5
g(x) = 2 ^ x
g(x)=2xg(x) = 2 ^ x
a = 4
a=4a = 4
b = 1
b=1b = 1
f(a) + g(b) - f(g(a+b))
f(a)+g(b)f(g(a+b))f(a) + g(b) - f(g(a+b))
f(a) + g(b) - f(g(a+b))
f(a)+g(b)f(g(a+b))f(a) + g(b) - f(g(a+b))
= (a + 5) + g(b) - (g(a+b) + 5)
=(a+5)+g(b)(g(a+b)+5)= (a + 5) + g(b) - (g(a+b) + 5)
f(x) = x + 5
f(x)=x+5f(x) = x + 5
= (a + 5) + 2 ^ b - (2^{a+b} + 5)
=(a+5)+2b(2a+b+5)= (a + 5) + 2 ^ b - (2^{a+b} + 5)
g(x) = 2 ^ x
g(x)=2xg(x) = 2 ^ x
a = 4, b = 1
a=4,b=1a = 4, b = 1
= (4 + 5) + 2 ^ 1 - (2^{4+1} + 5)
=(4+5)+21(24+1+5)= (4 + 5) + 2 ^ 1 - (2^{4+1} + 5)
= -26
=26= -26

How  versus  What

var numbers = ListBuffer(1, 2, 3, 4, 5)
var result = ListBuffer.empty[Int]

for(n <- numbers) {
  if(n % 2 == 0) result += n * n
}

imperative

val numbers = List(1, 2, 3, 4, 5)

def isEven(n: Int): Boolean = n % 2 == 0
def square(n: Int): Int = n * n

numbers.filter(isEven).map(square)

declarative

ex. square of even numbers

Imperative  versus  Declarative

val numbers = List(1, 2, 3, 4, 5)

def isEven(n: Int): Boolean = n % 2 == 0
def square(n: Int): Int = n * n

numbers.filter(isEven).map(square)
List(1, 2, 3, 4, 5).filter(isEven).map(square)
List(1, 2, 3, 4, 5).filter(n => n % 2 == 0).map(square)
List(2, 4).map(square)
List(2, 4).map(n => n * n)
List(4, 16)

evaluation

Functional Programming avoid side-effect !

THE PURITY

impure function  vs  pure function

var counter: Int = 0
var due: Int = 10

def tick(): Unit = {
  // side-effect!
  counter = counter + 1
}

def getRemainingTime(): Int = {
  // side-cause!
  due - counter
}

THESE ARE IMPURE !

MUTABLE STATE !!

impure function  vs  pure function

// create immutable object that holds data
case class Counter(current: Int, due: Int)

// return a new counter, doesn't mutate
def tick(counter: Counter): Counter =
  Counter(counter.current + 1, counter.due)

// explicit reference
def getRemainingTime(counter: Counter): Int =
  counter.due - counter.current

THESE ARE PURE

def join(separator: String, stringList: String*): String = {
  var result = ""
  for(s <- stringList) {
    result += separator + s
  }
  result.substring(1)
}

note that pure function can be imperative

Why is it so cool?

easier to reason about your code

changes are localized

easier to test

pure functions are deterministic

easier to do parallel programming

no race condition, no lock

enable declarative style

substitution model works only on pure funciton

You might ask:

But... without mutating state,

does it really work for real world problems?

How about I/O and databases?

When you can't avoid it, you have to control it.

Idempotent Operation

pure part

mutation

ISOLATE !

"spot side-effects in your code"

Hello functional programming

By Supanat IBoss Potiwarakorn