Tense Compositions

· updated 2026-06-01

CLEAR separates Tenses (Temporal, Optional, Failable) from pure memory layout (Types) from capabilities.

See Sharing Capabilities for more details.

Tenses:

Combinations:

To some, this may be considered far less readable than Rust/C style:

However, the further these compose with CLEAR's capabilities and failables, the harder Rust types are to read.

Compare simple cases:

CLEARRustWhat
~T[]@shared:lockedArc<RwLock<Pin<Box<dyn Stream<Item = T>>>>>The entire stream is thread-shared and locked.
~T[]impl Stream<Item = T>A basic asynchronous stream yielding Ts.
~(T[])@shared:lockedArc<RwLock<Future<Output = Vec<T>>>>A shared, locked future that resolves to an array.

Compare complex cases:

CLEARRustWhat
~(!?T[])impl Future<Output = Result<Option<Vec<T>>, Error>>A Future that eventually yields a
single, fallible, optional vector.

CLEAR reads better left to right:

CLEAR's tense system can look like Sigil Soup, but for the vast majority of cases it is more readable if you take a minute to learn the 3 sigils / tenses.

In the cases where you have tons of nested capabilities and tenses, CLEAR believes its system is much easier to parse to separate the concerns of what is important.

In short, CLEAR separates:

  1. What you need to do before you can use data (tenses),
  2. From the memory layout (types),
  3. From what you're allowed to do with it / how it can be shared, and optimizations on it (capabilities)

Order of symbols:

Tense symbols are read left-to-right.

Following the ordered list above, the come first (left most) because they dictate what must be done first to use the underlying data (the actual type):

If something is FOR SURE a future -> it starts with ~ no space for other tenses:

If something is FOR SURE fallible -> it starts with ! and a space & parens if other tenses:

If something is FOR SURE optional -> it starts with ? and a space & parens if other tenses:

Fallible optionals (typically bad design) are combined before a space:

When combined with arrays:

The leftmost character lets you know what you can do with it right away.

Therefore if something is fallible, the ! must come first:

Complex 2d arrays are NOT representable by design (as they do not make sense in terms of memory layout):

This is not unique to CLEAR. This is not allowed in Rust, C, or Go either.

Styling

Note that there is a space between optionals and errors, when combine with any non-trivial tense:

If you don't include the spaces and parentheses, the compiler will typically auto-correct it for you.

In practice, complex types like these are often created inline, via streaming pipelines, and you never need to know the correct formatting.

Streaming Arrays:

SyntaxSemantic MeaningCommonality
T[]Standard Array of TUltra-Common (100x)
?T[]Array of Optional TsCommon
~T[]Stream of Ts
(finite [N] or infinite [])
Common (5x more than Future Lists)
~?T[]Stream of Optional Ts
(unbounded, finite)
Common
? (T[])Optional Array of TsLess Common
~(T[])Future Array of TsLess Common
~(?T[])Future Array of Optional TsRare
~(T[])Future to an Optional ArrayRare
? (~T[])Optional Stream of TsUltra-Rare

Streaming HashMaps:

SyntaxSemantic MeaningReal-World Use Case
T{}Standard Map of TStoring a local cache of Users by their username.
?T{}Map of Optional TsA sparse matrix or a cache where keys can explicitly hold blank values.
~T{}Stream of Ts from a MapA live, reactive database view pushing updated values as they change.
~?T{}Stream of Optional TsA live feed pushing updates, where some updates delete the value.
? (T{})Optional MapA configuration block that is completely omitted in the settings file.
~(T{})Future MapGET /api/v1/config (Awaits and returns the full JSON map).
~?(T{})Future Optional MapFetching an optional block of data that might return 404/None.
m: ~T{} = getInfMap(); // infinite
m2: ~?T{} = getUnboundFiniteMap(); // unbound, finite

# Loop through mutations as they hit the map
WHILE NEXT m AS (key, value) {
    print("Key {key} changed to {value}");
}

# Loop through mutations as they hit the map
WHILE NEXT m2 AS (key, value) {
  IF value AS v {
    print("Key {key} changed to {v}");
  }
  ELSE {
    print("Key {key} was deleted");
  }
}
print("stream closed.");

Combine with failibility:

SyntaxSemantic MeaningCommonality
T[]Standard ArrayUltra-Common
!T[]Array of Fallible Elements
(you build an array / map of individual funcs that fail)
Common
~!T[]Stream of Fallible Elements (Your BG STREAM type)
(you BG STREAM a func that fails)
Common
! (T[])Fallible Array Container (Synchronous error)
(You return an array in a function that can fail)
Common
~(T[])Future ArrayLess Common
! ~(T[])Fallible Future Array (Standard Async API Fetch)Less Common
Some APIs
! (~T[])Fallible Stream (Stream closes if it errors)
You return a stream in a function that can fail
Rare
Some APIs

Source: docs/tense-composition.md