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?

twitter @theartfuldev

github @artfuldev

Functional Reactive Programming with Cycle.js

By artfuldev

Functional Reactive Programming with Cycle.js

  • 2,165
Loading comments...

More from artfuldev