Published
Edited
Apr 28, 2021
4 stars
Insert cell
Insert cell
Insert cell
{
const favorite_numbers = [42, 69, 73];
const increased_numbers = favorite_numbers.map(num => num + 1);
return increased_numbers;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function identity(x) {
return x;
}
Insert cell
Insert cell
{
const one = [1,2,3];
const two = [1,2,3].map(identity);
return str([one, two]);
}
Insert cell
Insert cell
Insert cell
function add_one(num) {
return num + 1;
}
Insert cell
function times_two(num) {
return num * 2;
}
Insert cell
{
const one = [1].map(add_one).map(times_two);
const two = [1].map(num => times_two(add_one(num)));
return str([one, two]);
}
Insert cell
Insert cell
Insert cell
// Identity
Promise.resolve(1).then(identity);
Insert cell
{
// Composition
const one = Promise.resolve(1).then(add_one).then(times_two);
const two = Promise.resolve(1).then(num => times_two(add_one(num)));
return Promise.all([one, two]);
}
Insert cell
Insert cell
List = ({
map(fn, arr) {
let result = [];
for (let data of arr) {
result.push(fn(data));
}

return result;
}
})
Insert cell
Insert cell
// Identity
List.map(identity, [1]);
Insert cell
{
// Composition
const one = List.map(times_two, List.map(add_one, [1]));
const two = List.map(num => times_two(add_one(num)), [1]);
return str([one, two]);
}
Insert cell
Insert cell
Obj = ({
map(fn, ob) {
let result = {};
for (let [key, value] of Object.entries(ob)) {
result[key] = fn(value);
}

return result;
}
})

// Why stop at `map`?
// Based on this you can also create a `filter` and `reduce`
Insert cell
Insert cell
// Identity
Obj.map(identity, {some: 1, prop: 2});
Insert cell
{
// Composition
const one = Obj.map(times_two, Obj.map(add_one, {some: 1, prop: 2}));
const two = Obj.map(num => times_two(add_one(num)), {some: 1, prop: 2});
return str([one, two]);
}
Insert cell
Insert cell
function Stream_v1(state) {
let stream = function(value) {
// If we get an argument we update the state
if(arguments.length > 0) {
state = value;
}

// return current state
return state;
}

return stream;
}
Insert cell
Insert cell
// Initial state
num_stream = Stream_v1(42);
Insert cell
// Get state
num_stream();
Insert cell
// Update
num_stream(73);
Insert cell
// Check updated state
num_stream();
Insert cell
Insert cell
function Stream_v2(state) {
let listeners = [];

let stream = function(value) {
if(arguments.length > 0) {
state = value;
listeners.forEach(fn => fn(value));
}

return state;
}

stream.map = function(fn) {
// Create new instance with transformed state.
// This will execute the callback when calling `map`
// this might not be what you want if you use a
// function that has side effects. Just beware.
let target = Stream_v2(fn(state));

// Transform the value and update stream
const listener = value => target(fn(value));

// Update the source listeners
listeners.push(listener);

return target;
}

return stream;
}
Insert cell
Insert cell
{
// Streams are like a cascade
// the first is the most important
// this is the one that triggers all the listeners
const num_stream = Stream_v2(0);

// Create dependent stream
const identity_stream = num_stream.map(identity);

// update the source
num_stream(42);

// Check
const one = num_stream();
const two = identity_stream();
return [one, two];
}
Insert cell
Insert cell
{
// Create source stream
const num_stream = Stream_v2(0);

// Create dependents
const map_stream = num_stream.map(add_one).map(times_two);
const composed_stream = num_stream.map(num => times_two(add_one(num)));

// Update source
num_stream(1);

// Check
const one = map_stream();
const two = composed_stream();
return [one, two];
}
Insert cell
Insert cell
{
function slug_str(value) {
return value.toLowerCase().replace(/\W/g, "-")
}
function update_header(text) {
viewof view.firstChild.textContent = text;
}

const title = Stream_v2('Initial title');
const slug = title.map(slug_str);
slug.map(update_header);
// Bind the input to header
viewof view.lastElementChild.addEventListener('input', e => title(e.target.value));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more