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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more