PostHole
Compose Login
You are browsing eu.zone1 in read-only mode. Log in to participate.
rss-bridge 2023-12-11T00:00:00+00:00

A Chain Reaction

The limits of my language mean the limits of my world.


A Chain Reaction

December 11, 2023

Pay what you like

I wrote a bit of JSX in my editor:

<p className="text-2xl font-sans text-purple-400 dark:text-purple-500">
Hello, <i>Alice</i>!
</p>

Right now, this information only exists on my device. But with a bit of luck, it will travel through time and space to your device, and appear on your screen.

Hello, Alice!

The fact that this works is a marvel of engineering.

Deep inside of your browser, there are pieces of code that know how to display a paragraph or draw text in italics. These pieces of code are different between different browsers, and even between different versions of the same browser. Drawing to the screen is also done differently on different operating systems.

However, because these concepts have been given agreed-upon names (<p> for a paragraph, <i> for italics), I can refer to them without worrying how they really work on your device. I can’t directly access their internal logic but I know which information I can pass to them (such as a CSS className). Thanks to the web standards, I can be reasonably sure my greeting will appear as I intended.

Tags like <p> and <i> let us refer to the built-in browser concepts. However, names don’t have to refer to something built-in. For example, I’m using CSS classes like text-2xl and font-sans to style my greeting. I didn’t come up with those names myself—they come from a CSS library called Tailwind. I’ve included it on this page which lets me use any of the CSS class names it defines.

So why do we like giving names to things?


I wrote <p> and <i>, and my editor recognized those names. So did your browser. If you’ve done some web development, you probably recognized them too, and maybe even guessed what would appear on the screen by reading the markup. In that sense, names help us start with a bit of a shared understanding.

Fundamentally, computers execute relatively basic kinds of instructions—like adding or multiplying numbers, writing stuff to memory and reading from it, or communicating with external devices like a display. Merely showing a <p> on your screen could involve running hundreds of thousands of such instructions.

If you saw all the instructions your computer ran to display a <p> on the screen, you could hardly guess what they’re doing. It’s like trying to figure out which song is playing by analyzing all the atoms bouncing around the room. It would seem incomprehensible! You’d need to “zoom out” to see what’s going on.

To describe a complex system, or to instruct a complex system what to do, it helps to separate its behavior into layers that build on each other’s concepts.

This way, people working on screen drivers can focus on how to send the right colors to the right pixels. Then people working on text rendering can focus on how each character should turn into a bunch of pixels. And that lets people like me focus on picking just the right color for my “paragraphs” and “italics”.

We like names because they let us forget what’s behind them.


I’ve used many names that other people came up with. Some are built into the browsers, like <p> and <i>. Some are built into the tools I’m using, like text-2xl and font-sans. These may be my building blocks, but what am I building?

For example, what is this?

<p className="text-2xl font-sans text-purple-400 dark:text-purple-500">
Hello, <i>Alice</i>!
</p>

Hello, Alice!

From your browser’s perspective, this is a paragraph with certain CSS classes (which make it large and purple) and some text inside (part of it is in italics).

But from my perspective, it’s a greeting for Alice. Although my greeting happens to be a paragraph, most of the time I want to think about it this way instead:

<Greeting person={alice} />

Giving this concept a name provides me with some newfound flexibility. I can now display multiple Greetings without copying and pasting their markup. I can pass different data to them. If I wanted to change how all greetings look and behave, I could do it in a single place. Turning Greeting into its own concept lets me adjust “which greetings to display” separately from “what a greeting is”.

However, I have also introduced a problem.

Now that I’ve given this concept a name, the “language” in my mind is different from the “language” that your browser speaks. Your browser knows about <p> and <i>, but it has never heard of a <Greeting>—that’s my own concept. If I wanted your browser to understand what I mean, I’d have to “translate” this piece of markup to only use the concepts that your browser already knows.

I’d need to turn this:

<Greeting person={alice} />

into this:

<p className="text-2xl font-sans text-purple-400 dark:text-purple-500">
Hello, <i>Alice</i>!
</p>

How would I go about that?


To name something, I need to define it.

For example, alice does not mean anything until I define alice:

const alice = {
firstName: 'Alice',
birthYear: 1970

Now alice refers to that JavaScript object.

Similarly, I need to actually define what my concept of a Greeting means.

I will define a Greeting for any person as a paragraph showing “Hello, ” followed by that person’s first name in italics, plus an exclamation mark:

function Greeting({ person }) {
return (
<p className="text-2xl font-sans text-purple-400 dark:text-purple-500">
Hello, <i>{person.firstName}</i>!
</p>

Unlike alice, I defined Greeting as a function. This is because a greeting would have to be different for every person. Greeting is a piece of code—it performs a transformation or a translation. It turns some data into some UI.

That gives me an idea for what to do with this:

<Greeting person={alice} />

Your browser wouldn’t know what a Greeting is—that’s my own concept. But now that I wrote a definition for that concept, I can apply this definition to “unpack” what I meant. You see, a greeting for a person is actually a paragraph:

function Greeting({ person }) {
return (
<p className="text-2xl font-sans text-purple-400 dark:text-purple-500">
Hello, <i>{person.firstName}</i>!
</p>

Plugging the alice’s data into that definition, I end up with this final JSX:

<p className="text-2xl font-sans text-purple-400 dark:text-purple-500">
Hello, <i>Alice</i>!
</p>

At this point I only refer to the browser’s own concepts. By substituting the Greeting with what I defined it to be, I have “translated” it for your browser.

Hello, Alice!

Now let’s teach a computer to do the same thing.


Take a look at what JSX is made of.

const originalJSX = <Greeting person={alice} />;
console.log(originalJSX.type);  // Greeting
console.log(originalJSX.props); // { person: { firstName: 'Alice', birthYear: 1970 } }

Under the hood, JSX constructs an object with the type property corresponding to the tag, and the props property corresponding to the JSX attributes.

You can think of type as being the “code” and props as being the “data”. To get the result, you need to plug that data into that code like I’ve done earlier.

Here is a little function I wrote that does exactly that:

function translateForBrowser(originalJSX) {
const { type, props } = originalJSX;
return type(props);

[...]


Original source

Reply