Denise Yu
I'm a software engineer. You can usually find me at the local pub, bouldering, or hunting for the best Korean fried chicken in London.
@gypsydave5 @deniseyu21
A quick-and-dirty intro to FP
Telling the computer how to do something
dogs_called_erik = [];
for (i = 0, i < dogs.length, i += 1) do
if dogs[i].name == 'Erik'
dogs_called_erik.push dogs[i]
end
end
Tell the computer what to do, but not how to do it
SELECT * FROM dogs
WHERE dogs.name = 'Erik'
In modern programming languages,
imperative and declarative are relative terms
"I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages... I wanted to get rid of data."
Alan Kay, creator of Smalltalk
class Dog
def initialize(name)
@name = name
end
def name
@name
end
def rename(new_name)
@name = new_name
end
def woof
"Woof!"
end
end
Functional programming only needs two things:
data and functions.
{
"languages": {
"object-oriented": [
"ruby",
"smalltalk"
],
"functional": [
"clojure"
]
}
}
y = f(x), where f(x) = x + 1
function woof (name) { return "Woof " + name + "!"; }
Not just a really, really fancy function.
def say_hello
"hello!"
end
say_hello
# "hello!"
# no, stupid Ruby! tell me what 'say_hello' is
say_hello = lambda { "hello!" }
say_hello
# <Proc:0x007ff9b2a59138@(irb):1 (lambda)>
say_hello.call
# "hello!"
function yo () {
return "yo!";
}
yo
// [Function: yo]
yo()
// "yo!"
Because
// so if
function sum (a, b) {
return a + b;
}
sum(1, sum(2, 3))
// is the same as
sum(1, 5)
function sum (a, b) {
const n = Math.random();
if (n < 0.5) {
return a + b;
} else {
return 'wtf';
}
}
sum(3, sum(1, 2))
// Maths only works sometimes here
let counter = 0;
function next (number) {
counter++;
return number + counter;
}
next(1); // 2
next(1); // 3
next(1); // 4
Not just a really, really innocent function.
let mutableVar = '';
function emitDirtyState () {
mutableVar += 'blah ';
return mutableVar;
}
This is impure:
function emitDirtyState () {
console.log("I'm a side effect");
return "yo";
}
This is impure:
function emitDirtyState () {
someNewGlobalVar = "wahoo!";
return "wtf?!?";
}
// you laugh, but this
// has been done before
This is REALLY impure:
cats = ["Felix", "Tom", "Puss in Boots", "Garfield"]
cats.map { |cat| cat.upcase }
// now JS!
cats.map(function(cat) { return cat.toUpperCase() })
// Suppose you have this amazing code
function addTwoTogether (a, b) {
return a + b;
}
// new code for new requirements
function addThree (a) {
return a + 3;
}
// old code
function addTwoTogether (a, b) {
return a + b;
}
// new code for new requirements
function addFive (a) {
return a + 5;
}
// old code
function addThree (a) {
return a + 3;
}
function addTwoTogether (a, b) {
return a + b;
}
// Great, but we only ever want to add 3
function addThree (a) {
return a + 3;
}
// JK, requirements change, now let's add 5, definitely
function addFive (a) {
return a + 5;
}
// User didn't like it, add 10 now... and so on and so on...
// and maybe more requirements change later
// shit, if only we had a way to automate this like the
// lazy-ass programmers we are.....
Haskell Curry
(just in case you didn't know)
// A simple arity-of-2 curry function
function curryTwoInputs (fun) {
return function (a) {
return function (b) {
return fun (a, b);
}
}
}
var _ = require('lodash');
function addTwoTogether (a, b) {
return a + b;
}
var curriedAddTwoTogether = _.curry(addTwoTogether);
var addTen = curriedAddTwoTogether(10);
addTen(5); // 15
// We can define new ones without manually writing a new function
var addEighteen = curriedAddTwoTogether(18);
addEighteen(20); // 38
Remember maths class?
f(x) = 2x
g(x) = x + 3
h(x) = f(g(x))
h(1) = f(g(1)) = f(4) = 8
(defn add
[a b]
(+ a b))
(add 4 5) ;; 9
(add 5 (add 3 (add 1 2))) ;; 11
// a simple arity-of-2 compose
function simpleCompose(fun1, fun2) {
return function (x) {
return fun1(fun2(x))
}
}
var _ = require('ramda');
addTwo(2) // => 4 ... remember this guy?
addTwo(addTen(2)) // => 14 ... we can keep feeding them in...
// We can toss functions together arbitrarily now
var addTwoThenTen = _.compose(addTwo, addTen);
addTwoThenTen(1); // 13
addTwoThenTen(100); // 114
var addFiveThenSeven = simpleCompose(addFive, addSeven);
addFiveThenSeven(10); // 22
addFiveThenSeven(0); // 12
var addAllTheThings = simpleCompose(addTwoThenTen, addFiveThenSeven);
def log_formatter(log)
log.group_by do |entry|
entry[:time]
end.values.map do |entries_by_time|
entries_by_time.reduce(:merge)
end
end
By Denise Yu