Some thoughts about functional programming
$ whoami
Erik Wallin
Consultant at DevCode
@c01ac0ca
Programming paradigms
Paradigm = Style (characteristics, concepts, thought patterns)
- Imperative
- Functional
- Logic
- Object Oriented
Logic programming
- Expressing facts and rules about some problem domain.
- Prolog
- https://bernardopires.com/2013/10/try-logic-programming-a-gentle-introduction-to-prolog/
Object oriented programming
- Objects with data and methods
- Encapsulation
- Polymorphism
- Message passing
- Etc
Imperative programming
- Modify mutable variables
- Control flows (if/else, loops, break, continue, return)
- Tell the machine how to do something
- Opposite: Declarative programming (Tell the machine what you would like to happen)
- Typical program
- cmd1; cmd2; cmd3; cmd4;
Functional programming
- Roots in lambda calculus
- No mutable variables
- No loops or break/continue/return
- Functions are "first-class citizens"
- Referentially transparent functions
- Typical program (or at least parts) with composition
- fn1(fn2(fn3(fn4, x, y)))
- "Pure" functional programming don't have side effects, i.e. updating state, print things on screen, etc
Functions are "first-class citizens"
- Functions defined everywhere, e.g. inside other functions
- Can be passed around as arguments to other functions
- Currying
- Methods may define multiple parameter lists. When a method is called with a fewer number of parameter lists, then this will yield a function taking the missing parameter lists as its arguments.
Referentially transparent functions
- An expression is said to be referentially transparent if it can be replaced with its value without changing the behaviour of a program
- Same input gives same output
- def plusone(x: Int): Int = x+1
Pure functional programming
-
Programming without side effects (???)
-
Don't mention the M-word!
- Vet du vad en Monad är? /erwa
- Jag vet vad en månad är. /joho
Links
- https://www.coursera.org/course/progfun
- https://www.coursera.org/course/reactive
Style vs language
A language can encourage a paradigm, but seldom decide completely
Functional languages
- Lisp
- Haskell
- XSLT
- XPath
Encouraging languages
- Scala
- F#
Functional programming in java
Combining functional and imperative programming
- Solve the business problems, discuss different solutions, be pragmatic
- See functional programming as a good tool in your toolbox
From xkcd
In the deepest scala library code we find a lot of imperative code
//List.scala
sealed abstract class List[+A] ...
override def drop(n: Int): List[A] = {
var these = this
var count = n
while (!these.isEmpty && count > 0) {
these = these.tail
count -= 1
}
these
}
...
Show us some code!
No mutable variables
// This is very strange for a mathematician
var x = x + 1
// Do instead
val y = x + 1
No loops or imperative control structures
// Imperative
def gcd(x: Int, y: Int): Int = {
var a = x
var b = y
while (a != b) {
if (a > b) {
a = a − b
} else {
b = b − a
}
}
return a;
}
// Functional way with recursion
def gcd(a: Int, b: Int): Int =
if (b == 0)
a
else
gcd(b, a % b)
Functions are first-class citiens
def id(x: Int): Int = x
def square(x: Int): Int = x * x
def powerOfTwo(x: Int): Int = if (x == 0) 1 else 2 * powerOfTwo(x - 1)
def sum(f: Int => Int, a: Int, b: Int): Int = f(a) + f(b)
//Composition
def sumInts(a: Int, b: Int): Int = sum(id, a, b)
def sumSquares(a: Int, b: Int): Int = sum(square, a, b)
def sumPowersOfTwo(a: Int, b: Int): Int = sum(powerOfTwo, a, b)
println("sum squares 2 and 4 = " + sumSquares(2, 4))
Lambda expressions
Anonymous functions
def sum(f: Int => Int, a: Int, b: Int): Int = f(a) + f(b)
println("sum quadruples 2 and 4 = " + sum(x => x * 4, 2, 4))
Closure
Function that uses variables declared outside of the function.
var factor = 3
val multiplier = i => i * factor
println("muliplier(1) value = " + multiplier(1))
println("muliplier(2) value = " + multiplier(2))
Currying
def modN(n: Int)(x: Int) = ((x % n) == 0)
def mod13 = modN(13)
println("modN(13, 8) value = " + modN(13, 8))
println("mod13(8) value = " + mod13(8))
Working with collections
If a java programmer should remember anything from this presentation this is it!
// Example from Oracle
// Imperative
List<Transaction> groceryTransactions = new Arraylist<>();
for (Transaction t: transactions) {
if(t.getType() == Transaction.GROCERY) {
groceryTransactions.add(t);
}
}
Collections.sort(groceryTransactions, new Comparator() {
public int compare(Transaction t1, Transaction t2) {
return t2.getValue().compareTo(t1.getValue());
}
});
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions) {
transactionsIds.add(t.getId());
}
// Declarative/Functional way
List<Integer> transactionsIds =
transactions.stream()
.filter(t -> t.getType() == Transaction.GROCERY)
.sorted(Comparator.comparing(Transaction::getValue).reversed())
.map(Transaction::getId)
.collect(toList());
Finally - Write clean code!
Single Abstract Method interfaces (SAM Interfaces) / Functional Interfaces
// Don't write a Comparator as a anonymous inner class
Collections.sort(groceryTransactions, new Comparator() {
public int compare(Transaction t1, Transaction t2) {
return t2.getValue().compareTo(t1.getValue());
}
});
// Use a lambda expression instead
Collections.sort(groceryTransactions,
(Transaction t1, Transaction t2) -> t2.getValue().compareTo(t1.getValue());
);
Some thoughts about functional programming
By Erik Wallin
Some thoughts about functional programming
- 771