A fully functional and reactive
JavaScript framework for cleaner code
AngularJS
React
Or, at the very least, something different!
A better way
(conveniently also the central idea of Cycle.js)
FRP is the culmination of Functional and Reactive Programing to achieve a more explicit dataflow with less magic and more
conciseness.
It helps you make your code cleaner and more understandable with very cohesive, decoupled units that are composable and testable.
Let's go one principle at a time
A way to make programs focusing on small, reusable functions.
Three core pillars:
Pure Functions
Composing Functions
Higher-order Functions
// PURE.
// Only operates on inputs.
// Does not modify external state.
// One input will give you only one output.
function sum(x, y) {
return x + y;
}
// IMPURE.
// Console defined elsewhere
// - doesn't operate on only inputs.
// Has a side effect on the console.
function log(thing) {
console.log(thing);
}
// IMPURE.
// Doesn't operate on only inputs.
// Modifies external state.
function getNetwork() {
// ... doing things with network
// (HTTP requests, etc)
}
// IMPURE.
// One input may give you many
// different outputs.
function silly(number) {
if (Math.random() > 0.5)
return number - 1;
return number;
}
Pure functions, generally, make it easier to understand, test, and reason about your code, because of the less wiring involved in using them.
Few examples
Composing functions is a technique to build bigger chunks of behavior from smaller chunks.
let isEven = (x) => x % 2 == 0;
let not = (val) = !val;
let isOdd = (x) = not(isEven(x))
Higher-order functions
are functions that can take functions as parameters.
// Takes a list and returns a new list with
// the given function applied to each of them
function map(func, list) {
let result = [];
for (val of list) {
result.push(val);
}
return result;
}
// Returns a list of values from the given list
// that the given function returns "true" for.
function filter(shouldInclude, list) {
let result = [];
for (val of list) {
if (shouldInclude(val))
result.push(val);
}
return result;
}
let evenSquaresOfOneDigits =
map(x => x * x,
filter(x => x % 2 == 0,
[1, 2, 3, 4, 5, 6, 7, 8, 9]));
You can use them in many ways.
Higher-order functions allow you to think of behavior as a series of transformations to data.
That covers functional, now let's look at reactive
A way to easily decouple functions
from each other and make any dependencies more clear.
a
c
b
"Others define when I should change"
a
c
b
"I define when I change, and due to what"
"Hey, set yourself to this value."
"Hey, this is my new value."
"OK"
"I can do whatever I want with it."
Event emmiters
Streams of events
Streams are collections, just like arrays...
Arrays
memory
1
2
3
...but they're spread over time, not memory
Streams
time
click!
click!
click!
Takes a stream of values, applies a given function to each of those values, and returns a stream with the new values.
Takes a stream of values, and returns a stream that only includes values that a given function returns true for.
Takes a stream of values, and creates a new stream that emits acculamated values according to a given function.
Takes a stream of streams, and "flattens" them into one stream that emits values from all the emitted streams.
Cycle.js is a fusion of functional and reactive programming that allows you to have the best of both worlds.
And then you can compose them, because they behave like literally any old function!
Sources are streams of inputs
from the outside world.
(User clicks, HTTP responses, really anything)
Sinks are streams of output
to the outside world.
(Rendered page, HTTP requests, again anything)
The outside world is represented by what are known as drivers. These are the impure functions, the only place where your code touches the external world.
They take in sinks from the main function, use the values from them to affect the world, and return inputs from the world as sources to the main function.
It's a... guess what?
A basic counter example, with increment and decrement buttons, and a number.
Explore more about Cycle.js at cycle.js.org