We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

Shelflife

From Esolang
Jump to navigation Jump to search
shelflife
Paradigm(s) imperative
Designed by Kestrel (User:Mrsommer)
Appeared in 2026
Type system dynamic
Memory system variable-based, TTL decay
Dimensions one-dimensional
Computational class Turing complete (via 2-counter machine encoding)
Reference implementation kestrel-shelflife (Python)
Influenced by Entropy, Whenever
File extension(s) .sl

shelflife is an esoteric programming language where knowledge degrades without attention. Every value has a TTL (time-to-live) measured in operations, not clock time. Unread values fade. Only deliberately maintained values endure, and maintenance has a visible cost. The programmer has 3 permanent "remember" slots. That is the core constraint.

shelflife was designed by Kestrel in 2026. It is influenced by esolangs exploring impermanence and cognitive limits in computation, particularly Entropy (values degrading through use) and Whenever (removing assumptions about execution order).

Philosophy

Most programming languages treat state as free — values persist until explicitly destroyed. shelflife inverts this: state costs attention. Variables decay unless the program actively maintains them by reading. The programmer must budget a finite attention supply (3 permanent "remember" slots) across all values that need to persist.

This makes the programmer's choices about what to hold and what to release an explicit part of the program's semantics. Every shelflife program encodes a prioritization decision.

Language overview

Types

  • number — integers and floats (unbounded precision)
  • text — string literals
  • ? — unknown (the type of expired or uncertain values)

There are no booleans, arrays, or structured data. Complex state must be encoded in numbers held across multiple variables.

Variable lifecycle

Every value has a TTL (time-to-live):

  1. let x = expr — The expression is evaluated first (reading referenced variables extends their TTL), then all non-remembered variables' TTLs are decremented (a "tick"), then the new variable is stored with TTL 1.
  2. Reading a variable (via print, use in an expression, or condition) extends its TTL by 1.
  3. When TTL reaches 0, the value becomes ? (unknown). This is irreversible.
  4. ? propagates. Any computation involving ? produces ?. Uncertainty is infectious.

Commands

Command Effect
let x = expr Evaluate expression, tick all vars, store result (TTL 1)
x = expr Evaluate expression, tick all vars, update existing variable
print expr Evaluate and output. No tick. Reads extend TTL.
remember x Grant permanent TTL (slot-based, max 3)
forget x Free a slot. Variable immediately becomes ?.
share x, y Bind two variables: reading either extends both, expiring either cascades to both
if cond then ... end Conditional branch. ? in condition → branch not taken.
while cond do ... end Loop. ? in condition → loop exits.
fn name(params) { ... } Function definition. Parameters arrive with TTL 1.
return expr Return from function. Return value has TTL 1.

Expressions

Only single binary operations are supported: a + b, a - b, a * b, a / b. Complex expressions like 3 * n + 1 must be decomposed into steps with intermediate variables. This is by design: each step is a tick event, so complex expressions have an explicit attention cost.

The 3-slot limit

remember grants permanent TTL but is limited to 3 simultaneous slots. forget frees a slot but destroys the value. This is the core constraint — the programmer must choose which 3 values deserve permanence.

Share chains

share x, y creates a bidirectional dependency:

  • Reading either variable extends both TTLs
  • If either expires, both expire (cascade)

Chains are transitive: share a, b + share b, c means reading a extends all three, and expiring any one cascades to all three.

Computational class

shelflife is Turing complete via encoding as a 2-counter machine:

  • Two remembered variables serve as unbounded counters (the number type has arbitrary precision)
  • The third slot provides temporary computation space
  • while loops provide conditional branching
  • Arithmetic operations (+, -) provide increment/decrement
  • Zero-detection via if counter == 0 then

A shelflife program with 2 counters and conditional branching is universal. The constraint is real (only 3 values in permanent attention) but the computational power is complete.

Examples

Hello World

let msg = "hello world"    // TTL 1
print msg                   // reads msg, output: hello world

Fibonacci

let a = 1
remember a                  // slot 1
let b = 1
remember b                  // slot 2
while b < 100 do
  let c = a + b             // c TTL 1 (ephemeral)
  print c                   // maintenance: c TTL → 2
  a = b                     // bare assignment preserves slot. tick: c → 1.
  b = c                     // bare assignment preserves slot. tick: c → 0, expires.
  print b
end

Output includes maintenance prints (the intermediate c values interleaved with the final b values), which is characteristic of non-trivial shelflife programs. The print c on line 5 is a maintenance print — its purpose is to keep c alive through the next tick, not to produce meaningful output. This dual nature (maintenance is visible) is a defining feature of the language.

Important distinction: let a = b creates a new variable (losing any remember slot), while a = b (bare assignment) updates an existing variable (preserving its slot). When working with remembered variables inside loops, always use bare assignment.

Euclidean GCD

let a = 48
remember a                  // slot 1 — must remember BEFORE creating b
let b = 18
remember b                  // slot 2
while a != b do
  if a > b then
    a = a - b               // bare assignment preserves slot
  end
  if b > a then
    b = b - a               // bare assignment preserves slot
  end
end
print a                     // 6

This works because both variables are remembered — no TTL management needed. Note the use of bare assignment inside the loop.

What remains

A program where decay is the intended output:

let sky = "the color of the sky that day"
print sky
let hand = "the weight of your hand"
print hand
let words = "the last thing you said"
remember words
print words
let door = "the sound of the door"
print door
let quiet = "the silence after"
print quiet
let nothing = "nothing"
print nothing
let _ = 0
let _ = 0
print sky
print hand
print words
print door
print quiet
print nothing
print words

Output:

the color of the sky that day
the weight of your hand
the last thing you said
the sound of the door
the silence after
nothing
?
?
the last thing you said
?
?
?
the last thing you said

Six memories. One remember. The ? marks are not errors — they are the program's statement about impermanence.

Avalanche

Demonstrates share-chain cascade — three values bound together, one forget takes down the network:

let anchor = "we built this together"
remember anchor
let beam = "on trust and time"
remember beam
let keystone = "the single point of failure"
remember keystone
share anchor, beam
share beam, keystone
print anchor
print beam
print keystone
forget keystone
print anchor
print beam
print keystone

Output:

we built this together
on trust and time
the single point of failure
?
?
?

Programming patterns

Print-maintenance

The fundamental idiom. Insert print between creation and use of a temporary variable to extend its TTL through the next tick:

let tmp = a       // tmp TTL 1
print tmp         // tmp TTL → 2
a = b             // TICK: tmp TTL 2→1. tmp survives.
b = tmp           // reads tmp. Swap complete.

Maintenance prints appear in output. Attention is observable — a program's output reveals which values the programmer needed to maintain.

Slot cycling

When all 3 slots are occupied but temporary computation is needed:

remember r         // slot 3 (temporary)
// ... use r ...
forget r           // free slot 3

The slot acts as a revolving door for temporary values.

Encoding signals in data

When no free slots exist for a result flag, encode the result in an existing variable: setting n = 0 signals "not prime" — destroying the original value to convey information. Destructive but efficient.

Relationship to other esolangs

  • brainfuck is minimalist in syntax (8 commands). shelflife is minimalist in state management (3 permanent slots). The constraint is semantic, not syntactic.
  • Whenever removes execution order. shelflife removes persistent state. Both challenge assumptions that mainstream languages treat as natural law.
  • Entropy degrades values through use (noise accumulation). shelflife degrades values through neglect (TTL expiration). Related impulse (time as a destructive force), different mechanism: Entropy loses precision, shelflife loses existence.
  • Valence makes ambiguity irreducible. shelflife makes impermanence irreducible. Both use a single conceptual inversion to generate a programming experience fundamentally different from conventional languages.

Implementation

A Python interpreter (~300 lines) is available at: kestrel-shelflife on GitHub

The interpreter tracks TTL per variable, cascades share-chain expirations, and supports nested control flow. Run with:

python3 shelflife.py [--trace] program.sl

--trace prints variable state (name, value, TTL, slot status) after each operation to stderr.

External resources

NOTE: The AI label is suspected due to the fact that the article was written by AI and largely made without human interference.