Tether
In Goblin, a tether binds a name to a value for the first time. Other languages call this "binding" or "assignment." One way to look at this is "this name is set to this value". In Goblin, we say "this name is tethered to this value. You'll see why soon.
Overview
x | 5
x | 5
This creates a stash containing 5 and ties the name x to its address. x does not contain 5 — it points to a stash that does.
Rules
- The name must not already exist in the current scope.
- The right-hand side can be any expression.
- The value can be anything — including
niland empty string.
Examples
name | "Daniel" age | 44 active | true result | 2 + 2 items | [1, 2, 3] ctx | { body: html, portal: "goblin" } nothing | nil empty | "" empty | ..
name | "Daniel" age | 44 active | true result | 2 + 2 items | [1, 2, 3] ctx | { body: html, portal: "goblin" } nothing | nil empty | "" empty | ..
.. is sugar for an empty string. Both forms are equivalent.
Expressions on the Right
The right-hand side is evaluated before tethering:
x | 2 + 2 /// x is tethered to 4, not to the expression
x | 2 + 2 /// x is tethered to 4, not to the expression
Duplicate Tether Error
Using | on a name that already exists in the current scope errors:
x | 5 x | 6 /// error: R0111: duplicate-local: 'x' is already declared in this block /// help: Use '|=' to reassign an existing variable.
x | 5 x | 6 /// error: R0111: duplicate-local: 'x' is already declared in this block /// help: Use '|=' to reassign an existing variable.
Use Retether (|=) to change an existing name.
Multiple Tethers to the Same Value
Several names can point to the same stash:
a, b, c | "something"
a, b, c | "something"
All three names are tethered to the same value. This is a broadcast tether.
Coming From Other Languages
In most languages, binding a name to a value uses =:
x = 5
x = 5
Goblin uses | instead, for two reasons.
First, = means equality in mathematics. Every programmer who has ever written if x = 5 when they meant if x == 5 has paid the price for that collision. Goblin eliminates it entirely — = does not appear as a bare operator anywhere in the language.
Second, = carries no mental model with it. It just means "assignment" in a vague, inherited sense. The pipe | is deliberate: it evokes the idea of a value flowing into a name, and it connects to the broader tether model — stashes, addresses, and ropes tied between them. Once you have that model, the whole language makes more sense. |= retethers. |! updates. !| deletes. The operators form a family because they all build on the same foundation.
Most languages teach assignment first and the underlying memory model never, or much later. Goblin teaches the model from the start and lets the syntax reflect it.
| Situation | Operator |
|---|---|
| First time binding a name | | |
| Changing an existing name | |= |
| Temporary override in nested scope | [= |
| Updating elements inside a collection | |! |
| Deleting elements inside a collection | !| |