Platform
Resources
Pricing
Sign in
Get started
Max Bo
Software Engineer @ Canva, ex-Google | music, color theory, Australian democracy, situated software & generative art
Workspace
Fork
Public
Talks
By
Max Bo
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
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.
Try it for free
Learn more
Fork
View
Export
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
ourTagFunction
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
xs
Edit
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
generator
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
echo
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
anotherGenerator
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
yetAnotherGenerator
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
asyncGenerator
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
accumulate
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
captureNextPageLink
Edit
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
paginateGithubAPI
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
pages
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
makeChannel
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
chan
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
target
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
handler
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
debugProxy
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
validator
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
user
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
range
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML