Sign up

Seamless Notes

Not verified No WebSub updates No webmention support Not yet validated

Notes on building a typed, Wasm-first language substrate for the web.

Generator
Hugo
Public lists
I ♥ RSS
Fetched

Seamless Notes

The Host Is an Explicit Boundary

Earlier posts looked at boundaries within Seamless itself: regions contain mutation, expanded code goes through ordinary checking, and failures remain explicit. The next boundary is literal: the one between Seamless code compiled to WebAssembly and the host that gives it access to the outside world.

WebAssembly can calculate, allocate, and manipulate its own memory, but it cannot open a file, write to a terminal, make an HTTP request, start a timer, or update the DOM by itself. Those operations belong to the host: Node, a browser, Wasmtime, or some other embedding environment.

Seamless Notes

Macros Without Magic

The previous two design pillars of Seamless are crash-safety and immutability. Both are about reducing cognitive load, removing hidden order of execution and spooky action at a distance, and thus maximizing the ability to reason locally.

The next design pillar is extensibility.

Language extensibility is about being able to fit the language and program structure to the problem domain, instead of fitting the domain into a rigid set of structures and language abstractions. As Paul Graham argued, regularity in a program that does not follow the shape of the problem domain is probably a sign of a missing abstraction.

Seamless Notes

Why Mutation Should Stay Local

The previous post explored crash-safety and explicit failure as a main design pillar of Seamless.

The next pillar is immutability: ordinary application data should be immutable by default.

Shared mutable state makes code hard to reason about. If a value can be changed from somewhere else, every use of that value has to consider what else might have happened. That is exactly the kind of uncertainty I want ordinary Seamless code to avoid.

Seamless Notes

Don't let it crash

One of the primary design pillars of Seamless is crash-safety.

Ordinary Seamless code should never crash the program.

If an operation can fail in a recoverable way, the caller should be able to see that in the value it returns.

A common version of this is selecting an item from application data:

function selectedPlanName(plans, selectedId) {
 const matches = plansWithId(plans, selectedId);
 return matches[0].name;
}

Is it safe? Are we really sure that the matches will never be empty?

Seamless Notes

A small tour of Seamless

This is a short orientation to the language as it exists today.

It is not meant to be a complete tutorial. The syntax is still moving, names are still provisional, and some parts of the language are more mature than others. The goal here is only to make the examples in these notes easier to follow.

Values and primitive types

Seamless is statically typed, and the types are inferred. Values have types such as:

Seamless Notes

An apple pie from scratch

If you wish to make an apple pie from scratch, you must first invent the universe.

— Carl Sagan

That quote kept coming back to me because the deeper I pushed on the web-stack problem, the more the “reasonable” solution started to look like inventing the universe.

The component model always felt like the right direction for UI: local state, composition, data flowing into views, and interfaces described from application state instead of manually coordinated DOM updates.