Functional
Reactive
Programming
with
Cycle.js
https://slides.com/artfuldev/frp-with-cycle-js/live/
Functional
Reactive
Cycle.js
Functional?
Reactive
Cycle.js
Functional?
Reactive?
Cycle.js
Functional?
Reactive?
Cycle.js?
Functional?
Reactive?
Cycle.js?
How to write great apps?
How to write great apps?
-
Simplicity
How to write great apps?
-
Simplicity
-
Clarity
If I can read the source code and understand what happens
Then most likely it will work
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
Where does this get data from?
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
Where does this get data from?
Does this get modified?
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
Where does this get data from?
Does this get modified?
How does this happen?
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
What if getTodos() gets called again?
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
What if getTodos() gets called again?
while the save is still executing?
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
Functions everywhere
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
Functions everywhere
Functional
const todos = getTodos();
const updatedTodos = addNewTodo(todos, newTodo);
saveTodos(updatedTodos);
Functions everywhere
Functional
A way to write programs in terms of simple functions
Great functions are...
Great functions are...
- Small
Great functions are...
- Small
- Simple
Great functions are...
- Small
- Simple
- Pure
Functional Refactoring
Given an array of numbers, multiply each number by a constant and print the result.
var numbers = [3, 1, 7];
var constant = 2;
// 6 2 14
Functional Refactoring
Given an array of numbers, multiply each number by a constant and print the result.
var numbers = [3, 1, 7];
var constant = 2;
// Imperative / Prodedural
for(var i = 0; i < numbers.length; i++) {
console.log(numbers[i] * constant);
}
// 6 2 14
var numbers = [3, 1, 7];
var constant = 2;
// Imperative / Prodedural
for(var i = 0; i < numbers.length; i++) {
console.log(numbers[i] * constant);
}
// 6 2 14
var numbers = [3, 1, 7];
var constant = 2;
// Imperative / Prodedural
for(var i = 0; i < numbers.length; i++) {
console.log(numbers[i] * constant);
}
// 6 2 14
- for loop is a pain to debug and use
var numbers = [3, 1, 7];
var constant = 2;
// Imperative / Prodedural
for(var i = 0; i < numbers.length; i++) {
console.log(numbers[i] * constant);
}
// 6 2 14
- for loop is a pain to debug and use
- mixing data manipulation with printing
var numbers = [3, 1, 7];
var constant = 2;
// Imperative / Prodedural
for(var i = 0; i < numbers.length; i++) {
console.log(numbers[i] * constant);
}
// 6 2 14
- for loop is a pain to debug and use
- mixing data manipulation with printing
- code is hard to reuse
Simple
Simple
A function does one thing, and one thing only
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
// 6 2 14
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
// 6 2 14
multiplies 2 numbers
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
// 6 2 14
multiplies 2 numbers
prints 1 argument
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
const result = product.bind(null, constant);
// result(x) is the same as product(constant, x)
// 6 2 14
Making new functions
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
const result = product.bind(null, constant);
// result(x) is the same as product(constant, x)
// 6 2 14
Making new functions
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
const result = product.bind(null, constant);
// result(x) is the same as product(constant, x)
// 6 2 14
Making new functions
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
const result = product.bind(null, constant);
// result(x) is the same as product(constant, x)
function printResult(x) {
print(result(x));
}
// 6 2 14
Composition
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
const result = product.bind(null, constant);
// result(x) is the same as product(constant, x)
function printResult(x) {
print(result(x));
}
// 6 2 14
Composition
One function, one variable
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
const result = product.bind(null, constant);
function printResult(x) {
print(result(x));
}
for(var i = 0; i < numbers.length; i++) {
printResult(numbers[i]);
}
// 6 2 14
Refactoring
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
const result = product.bind(null, constant);
function printResult(x) {
print(result(x));
}
for(var i = 0; i < numbers.length; i++) {
printResult(numbers[i]);
}
// 6 2 14
Refactoring
simple, small, reusable functions
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
const result = product.bind(null, constant);
function printResult(x) {
print(result(x));
}
for(var i = 0; i < numbers.length; i++) {
printResult(numbers[i]);
}
// 6 2 14
Refactoring
simple, small, reusable functions
application logic functions
var numbers = [3, 1, 7];
var constant = 2;
function product(a, b) {
return a * b;
}
function print(x) {
console.log(x);
}
const result = product.bind(null, constant);
function printResult(x) {
print(result(x));
}
for(var i = 0; i < numbers.length; i++) {
printResult(numbers[i]);
}
// 6 2 14
Refactoring
simple, small, reusable functions
application logic functions
iteration
var numbers = [3, 1, 7];
var constant = 2;
for(var i = 0; i < numbers.length; i++) {
printResult(numbers[i]);
}
// 6 2 14
Iteration
var numbers = [3, 1, 7];
var constant = 2;
for(var i = 0; i < numbers.length; i++) {
printResult(numbers[i]);
}
// 6 2 14
Iteration
numbers.forEach(printResult);
var numbers = [3, 1, 7];
var constant = 2;
for(var i = 0; i < numbers.length; i++) {
printResult(numbers[i]);
}
// 6 2 14
Iteration
numbers.forEach(printResult);
same result
var numbers = [3, 1, 7];
var constant = 2;
for(var i = 0; i < numbers.length; i++) {
printResult(numbers[i]);
}
// 6 2 14
Iteration
numbers.forEach(printResult);
same result
numbers // [3, 1, 7]
.map(result) // [6, 2, 14]
.forEach(print); // 6 2 14
var numbers = [3, 1, 7];
var constant = 2;
for(var i = 0; i < numbers.length; i++) {
printResult(numbers[i]);
}
// 6 2 14
Iteration
numbers.forEach(printResult);
same result
numbers // [3, 1, 7]
.map(result) // [6, 2, 14]
.forEach(print); // 6 2 14
clearer semantics
Pure Functions
- Only use input arguments
function product(a, b) {
return a * b;
}
Pure Functions
- Only use input arguments
- Do not modify anything outside
(have no observable side effects)
function product(a, b) {
return a * b;
}
Pure Functions
- Only use input arguments
- Do not modify anything outside
(have no observable side effects) - return the same result for the same
inputs every time
function product(a, b) {
return a * b;
}
Pure Functions
- Only use input arguments
- Do not modify anything outside
(have no observable side effects) - return the same result for the same
inputs every time
function print(x) {
console.log(x);
}
Pure Functions
- Only use input arguments
- Do not modify anything outside
(have no observable side effects) - return the same result for the same
inputs every time
function print(x) {
console.log(x);
}
not pure
console is defined outside
Pure Functions
- Only use input arguments
- Do not modify anything outside
(have no observable side effects) - return the same result for the same
inputs every time
function print(x) {
console.log(x);
}
not pure
has side effects on the terminal
Pure Functions
- Only use input arguments
- Do not modify anything outside
(have no observable side effects) - return the same result for the same
inputs every time
function getTime() {
return new Date();
}
Pure Functions
- Only use input arguments
- Do not modify anything outside
(have no observable side effects) - return the same result for the same
inputs every time
function getTime() {
return new Date();
}
not pure
does not operate on inputs?
Pure Functions
- Only use input arguments
- Do not modify anything outside
(have no observable side effects) - return the same result for the same
inputs every time
function getTime() {
return new Date();
}
not pure
does not operate on inputs? not really
Pure Functions
- Only use input arguments
- Do not modify anything outside
(have no observable side effects) - return the same result for the same
inputs every time
function getTime() {
return new Date();
}
not pure
does not return same outputs every time
Pure Functions
-
Simple to write
-
Simple to read
-
Simple to test
function product(a, b) {
return a * b;
}
My Advice
My Advice
-
Write small, simple, pure functions
My Advice
-
Write small, simple, pure functions
-
Try to compose for complex logic
My Advice
-
Write small, simple, pure functions
-
Try to compose for complex logic
-
Progress slowly through the codebase
Functional?
Reactive?
Cycle.js?
A way to write programs in terms of simple functions
Functional?
Reactive?
Cycle.js?
A way to write programs in terms of simple functions
var a = 3;
var b = 5;
var c = a + b;
// c is 8
var a = 3;
var b = 5;
var c = a + b;
// c is 8
a = -3;
// c is still 8
var a = 3;
var b = 5;
var c = a + b;
// c is 8
a = -3;
// c is still 8
I want c to be recomputed whenever a or b changes
var c = a + b;
Set c to the value of a + b
var c = a + b;
???
Declare c to be the
sum of a and b
Set c to the value of a + b
var a = 3;
var b = 5;
var c = a + b;
// c is 8
a = -3;
// c is still 8
var a = 3;
var b = 5;
var c = a + b;
// c is 8
a = -3;
// c is still 8
c = a + b;
// c is now 3
var a = 3;
var b = 5;
var c = a + b;
// c is 8
a = -3;
// c is still 8
c = a + b;
// c is now 3
We need to call "c = ..." every time, to set it to the new value
Proactive
a
b
c
Proactive
Every code updating a or b also has to update c
a
b
c
Proactive
Every code updating a or b also has to update c
a
b
c
Proactive
Ties a and b very closely to c
a
b
c
Reactive
Reactive
Spreadsheets?
Reactive
Spreadsheets?
Proactive
a and b also update c whenever they are updated
a
b
c
Reactive
c updates itself whenever there is a change in
a or b
a
b
c
Reactive
a and b emit events, c updates itself when an event arrives
a
b
c
Reactive
a and b emit events, c updates itself when an event arrives
a
b
c
0
Reactive
a and b emit events, c updates itself when an event arrives
a
b
c
0
3
Reactive
a and b emit events, c updates itself when an event arrives
a
b
c
3
3
Reactive
a and b emit events, c updates itself when an event arrives
a
b
c
3
5
3
Reactive
a and b emit events, c updates itself when an event arrives
a
b
c
8
3
5
Reactive
a and b emit events, c updates itself when an event arrives
a
b
c
8
5
-3
Reactive
a and b emit events, c updates itself when an event arrives
a
b
c
2
5
-3
Reactive
a
b
c
2
5
-3
Reactive
a
b
c
2
5
-3
Reactive
a
b
c
2
5
-3
?
?
What are a and b?
What are a and b?
What are a and b?
Custom Code
What are a and b?
Custom Code
Event Emitters
What are a and b?
Custom Code
Event Emitters
Streams
What are a and b?
Streams
What are streams?
What are streams?
Streams are collections, like arrays
What are streams?
const numbers = [1, 2, 3];
numbers.forEach(print);
// 1 2 3
Streams are collections, like arrays
What are streams?
Streams are collections, like arrays
const numbers = [1, 2, 3];
numbers.forEach(print);
// 1 2 3
numbers.push(100);
// nothing happens
What are streams?
Streams are collections, like arrays, but whereas
arrays are
collections over space,
streams are
collections over time
next, error, complete
next, error, complete
A stream can emit indefinitely, or terminate with error or complete events
next, error, complete
A stream can emit indefinitely
// stream that never emits
// -------------------
// stream that never ends
// ----1---2-3----4-5-
// stream that terminates with error
// ----1---2---3----X
// stream that terminates with complete
// --1---2-3--4-|
Marble Diagrams
// stream that never emits
// -------------------
// stream that never ends
// ----1---2-3----4-5-
// stream that terminates with error
// ----1---2---3----X
// stream that terminates with complete
// --1---2-3--4-|
Marble Diagrams
and operators
Reactive?
Reactive?
A way to write programs using explicit data flows and propagation of change
Functional?
Reactive?
Cycle.js?
A way to write programs in terms of simple functions
A way to code with data flows and propagation of change
Functional?
Reactive?
Cycle.js?
A way to write programs in terms of simple functions
A way to code with data flows and propagation of change
Remember pure functions?
Cycle.js
lets you write
your entire app
as a single
pure function
Cycle.js
bringing the advantages
of pure functions
with it
Cycle.js
apps
So,
Cycle.js
apps
So,
are functional & reactive
Cycle.js
apps
So,
are functional & reactive
are simple & concise
Cycle.js
apps
So,
are functional & reactive
are simple & concise
are extensible & testable
Cycle.js
apps
So,
are functional & reactive
are simple & concise
are extensible & testable
have explicit data flow
Cycle.js
apps are pure functions,
Also, since your
Cycle.js
apps are pure functions,
Also, since your
they are
Cycle.js
apps are pure functions,
Also, since your
they are
composable
just like functions
Cycle.js
apps are pure functions,
Also, since your
they are
composable
just like functions
(your app can run inside another Cycle.js app)
Let's talk with examples
Let's talk with examples
Problem: Create a simple application that has a counter with increment and decrement buttons
Problem: Create a simple application that has a counter with increment and decrement buttons
Problem: Create a simple application that has a counter with increment and decrement buttons
import xs from 'xstream';
import { run } from '@cycle/xstream-run';
import { div, button, p, makeDOMDriver } from '@cycle/dom';
function main(sources) {
const intent$ = xs.merge<number>(
sources.DOM.select('.decrement').events('click').map(ev => -1),
sources.DOM.select('.increment').events('click').map(ev => 1)
);
const count$ = intent$.fold((count, intent) => count + intent, 0);
return {
DOM: count$.map(count =>
div([
button('.decrement', 'Decrement'),
button('.increment', 'Increment'),
p('Counter: ' + count)
])
)
};
}
run(main, {
DOM: makeDOMDriver('#app')
});
A litte more complicated this time...
Cycle.js
A functional and reactive JavaScript framework for cleaner code
Functional?
Reactive?
Cycle.js?
A way to write programs in terms of simple functions
A way to code with data flows and propagation of change
A functional and reactive framework for cleaner code
Functional?
Reactive?
Cycle.js?
A way to write programs in terms of simple functions
A way to code with data flows and propagation of change
A functional and reactive framework for cleaner code
This stuff is great!
How do I get to learn more about all this?
Cycle.js docs are fantastic
Cycle.js community is very friendly and helpful
Cycle.js
Uses functional reactive streams to describe the data flow in application
Cycle.js
Side effects (DOM, HTTP, etc) are isolated via drivers
Cycle.js
Works out of the box with real time backends (WebSockets, IoT)
Questions?
slides artfuldev/frp-with-cycle-js/
twitter @theartfuldev
github @artfuldev
Functional Reactive Programming with Cycle.js
By artfuldev
Functional Reactive Programming with Cycle.js
- 5,267