ddonche/goblin-lang
0.46.24
1
0
example documentation
[[nullish-coalesce]]

Nullish Coalesce & Guard


In Goblin, the ?? operator and its guarded form ?? => let you handle nix values cleanly and concisely.

Note
Nix is a special Goblin keyword that means "nil or empty". It covers both.

Nullish Coalesce (??)

What you write

x | maybe_value ?? fallback
x | maybe_value ?? fallback

What it does

If the left-hand value is not nix, it is used.

If it is nix, the fallback is used instead.

x | nil ?? 5
x  /// -> 5
x | nil ?? 5
x  /// -> 5

x | "hello" ?? "fallback"
x  /// -> "hello"
x | "hello" ?? "fallback"
x  /// -> "hello"


Nullish Guard (?? =>)

What you write

x | maybe_value ?? => action
x | maybe_value ?? => action

What it does

This form does not replace the value.

Instead, it:

  1. Tethers the value normally
  2. If the value is nix, runs the action

Equivalent to:

x | maybe_value
if x.nix? => action
x | maybe_value
if x.nix? => action


Example

x | nil ?? => :say("hit")
x | nil ?? => :say("hit")

Output:

hit
x  /// -> nil
hit
x  /// -> nil


Non-nix case

x | 1 ?? => :say("hit")
x | 1 ?? => :say("hit")

Output:

(no output)
x  /// -> 1
(no output)
x  /// -> 1


Works with Retether (|=)

x | nil
x |= 1 ?? => :say("hit")
x | nil
x |= 1 ?? => :say("hit")

Since 1 is not nix, nothing happens.

x  /// -> 1
x  /// -> 1


Inline Guard Actions

The right-hand side of => can be any single statement, including another inline if:

x | nil ?? => if true => :say("nested")
x | nil ?? => if true => :say("nested")

Output:

nested
nested


Early Return Pattern

The most common use of ?? => is returning early from an action when a value is nix:

act process(x)
    body | x ?? => return ""
    return body
xx

This replaces the two-line pattern:

body | x
if body.nix? => return ""


Formatting Notes

Inline form (preferred)

x | nil ?? => :say("hit")
x | nil ?? => :say("hit")

Tight form (also valid)

x | nil ??=> :say("hit")
x | nil ??=> :say("hit")

Multiline form (not supported)

x | nil ??
=> :say("hit")
x | nil ??
=> :say("hit")

This will currently produce a parse error.


How it differs

Form Behavior
?? Replaces nix with a fallback value
?? => Keeps the value, but runs an action if nix

Why this exists

Goblin treats nil and empty values as a unified concept: nix.

These operators provide two clean patterns:

  • Recover from nix??
  • React to nix?? =>

This keeps logic compact without breaking the flow of tethering.