Public
Edited
Dec 13, 2023
1 fork
12 stars
Insert cell
Insert cell
Insert cell
Insert cell
`we can create single line strings`
Insert cell
`but they can also
stretch over multiple lines`
Insert cell
`we can also interpolate an ${"ARBITRARY EXPRESSION".toLowerCase()} into these template literals`
Insert cell
Insert cell
function ourTagFunction(string, ...args) {
// can capture interpolation data...
// ...and return arbitrary data
return { string, args };
}
Insert cell
ourTagFunction`can intercept ${"arbitrary"} interpolations of ${"expression"}s and return arbitrary data`
Insert cell
Insert cell
dot`digraph { "parse GraphViz DOT" -> "return SVG"; }`
Insert cell
// this implements a fullblown HTML parser (https://github.com/observablehq/htl)
htl.html`
<form>
<label>
${["parse HTML", "and return HTML elements"].map((entry) => htl.html`<button>${entry}</button>`)}
</form>
`
Insert cell
tex`\text{or parse} ~ \TeX \wedge \text{return HTML elements}`
Insert cell
Insert cell
Insert cell
Insert cell
xs[Symbol.iterator]()
Insert cell
Insert cell
Insert cell
{
const iter = xs[Symbol.iterator]();
return [iter.next(), iter.next(), iter.next(), iter.next()];
}
Insert cell
Insert cell
Insert cell
function* generator() {
yield 1;
yield 2;
yield 3;
return "return";
}
Insert cell
Insert cell
{
const gen = generator();
return [gen.next(), gen.next(), gen.next(), gen.next()];
}
Insert cell
Insert cell
Insert cell
function* echo() {
/* resume next(0) -> */
const a = /* resume next(1) <- suspension point */ yield undefined;
const b = /* resume next(2) <- suspension point */ yield a;
const c = /* resume next(3) <- suspension point */ yield b;
return { a, b, c };
}
Insert cell
{
const gen = echo();
return [gen.next(0), gen.next(1), gen.next(2), gen.next(3) ];
}
Insert cell
Insert cell
Insert cell
[...generator()]
Insert cell
Insert cell
function* anotherGenerator() {
yield* [4, 5, 6];
}
Insert cell
[...anotherGenerator()]
Insert cell
Insert cell
function* yetAnotherGenerator() {
yield "prior";
const lvalue = yield* generator();
yield "interleave";
yield lvalue;
}
Insert cell
[...yetAnotherGenerator()]
Insert cell
function* asyncGenerator() {
yield 1;
yield Promises.delay(2000).then(() => 2);
yield Promises.delay(3000).then(() => 3);
yield 4;
yield Promises.delay(5000).then(() => 5);
}
Insert cell
asyncGenerator()
Insert cell
[...asyncGenerator()]
Insert cell
Insert cell
async function* accumulate(g) {
const xs = [];

for await (const v of g) {
xs.push(v);
yield xs;
}
}
Insert cell
Insert cell
accumulate(asyncGenerator())
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
async function* paginateGithubAPI(url, pageLimit) {
do {
const result = await fetch(url);
yield result.json();

const linkHeader = result.headers.get("link");
if (!linkHeader) return;
url = linkHeader.match(captureNextPageLink)[1];
} while (--pageLimit);
}
Insert cell
Insert cell
Insert cell
pages = accumulate(
paginateGithubAPI(
"https://api.github.com/orgs/github/repos",
/*pageLimit=*/ 10
)
)
Insert cell
Insert cell
Insert cell
function makeChannel() {
let input;
// https://github.com/observablehq/stdlib/blob/main/src/generators/observe.js
const output = Generators.observe((change) => {
input = change;
});

return { input, output };
}
Insert cell
chan = makeChannel()
Insert cell
chan.input(Date.now())
Insert cell
Insert cell
accumulate(chan.output)
Insert cell
Insert cell
Insert cell
target = ({
key: "value"
})
Insert cell
Insert cell
handler = ({
get(target, prop) {
return { target, prop };
}
})
Insert cell
Insert cell
debugProxy = new Proxy(target, handler)
Insert cell
debugProxy.key
Insert cell
debugProxy.arbitrary
Insert cell
Insert cell
validator = ({
set(obj, prop, value) {
if (prop === "age") {
if (!Number.isInteger(value)) {
// Indicate failure
return false;
}
if (value > 200) {
throw new RangeError("The age seems invalid");
}
}

// The default behavior to store the value
obj[prop] = value;

// Indicate success
return true;
}
})
Insert cell
user = new Proxy({ age: 30 }, validator)
Insert cell
(user.age = 53)
Insert cell
(user.age = "young")
Insert cell
(user.age = 201)
Insert cell
Insert cell
function range(start, finish) {
function* go() {
for (; start < finish; ++start) {
yield start;
}

return;
}

const handler = {
has(target, key) {
return start <= key && key < finish;
}
};

return new Proxy(go(), handler);
}
Insert cell
5 in range(1, 10)
Insert cell
Insert cell
Promises.delay(1000).then(() => 1)
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