Functional JavaScript and Ramda.js
Zhuoran (John) Li
What is FP? 🤯
A programming paradigm mapped from mathematical functions
Declarative
(what)
Imperative
(how)
vs
🥳
Pure Function 💦
Given the same input, will always return the same output and produces no side effects
// Pure
const add = (a, b) => a + b
add(1, 2) // 3
add(1, 2) // 3
[1, 2, 3].slice(0, 1) // [1]
// Impure
let a = 1;
const increment = n => a += n
increment(1) // 2
increment(1) // 3
[1, 2, 3].splice(0, 1) // [1]
Math.random() // 0.8227538687335922
Math.random() // 0.6780092463695311
In Reducer
Side Effects ✍️
- I/O (reading and writing a file)
- Calling an API to modify an object
- Mutations
- Calling any other functions with side-effects
Using side effects is NOT forbidden!
Currying
Transforms a function with multiple arguments into a sequence/series of functions each taking a single argument.
const add = a => b => a + b
const increment = add(1)
const increment(2) // 3 === add(1)(2)
Pointfree Style!
Cleaner and More Expressive
const water = cond([
[equals(0), always('water freezes at 0°C')],
[equals(100), always('water boils at 100°C')],
[T, temp => `nothing special happens at ${temp}°C`]
])
const isEligibleToVote = both(isOverEighteen, isCitizen)
const water = temperature => cond([
[val => equals(0, val), val => always('water freezes at 0°C')],
[val => equals(100, val), val => always('water boils at 100°C')],
[T, temp => `nothing special happens at ${temp}°C`]
])(temperature)
const isEligibleToVote = age =>
both(
val => isOverEighteen(val),
val => isCitizen(val)
)(age)
Another Example
(code snippet from our product)
🥳 After
🤪 Before
Function Composition
Applying a function to the output of another function
h(g(f(x)))
compose(h, g, f)(x)
const toAlladin = compose(g, f)
toAlladin(aPerson)
const toAlladin = pipe(f, g)
toAlladin(aPerson)
compose: right -> left
pipe: left -> right
Example
More Examples
(Code snippet from our product)
Functors
🤓 Simplified Answer:
A functor is an object that has a map method
Better Answer
🧐 A functor in an object that obeys the functor laws
Identity and Associativity
// Identity
[2].map(x => x) === [2]
// Associativity
const f = x => x * 2
const g = x => x + 2
[2].map(g).map(f) === [2].map(compose(f, g)) // [8] [8]
UI Design:
- Initial state
- Loading state
- Success state
- Error state
Initial
(Not Asked)
Verifying One-time URL
(Loading)
Invalid URL
(Failure)
Valid URL
(Success)
Remote Object - Tagged Union (Sum Types)
Verifying One-time URL
Error (e.g. Invalid Reset Password URL)
Initial State
Success
You can chain Remote during rendering
Productivity plugin in Alfred
The End