Guarded Destructuring
In Goblin, you can destructure values into bindings while declaring:
- required fields (
<req>) - default values (
:) - fallback behavior (
=>)
This is called Guarded Destructuring.
It ensures that:
- Missing values are always handled
- Required values are always enforced
- Defaults are always applied when provided
- Failures are always resolved explicitly
There are no unhandled states.
Basic Shape
a<req>, b:"x", c | expr => fallback
a<req>, b:"x", c | expr => fallback
What it does
-
Evaluates
expr -
Destructures positionally into bindings
-
Applies defaults:
- Explicit defaults (
b:"x") - Implicit fallback for unmarked bindings →
""
- Explicit defaults (
-
Checks required bindings (
<req>) -
If any required binding is nix:
- The entire expression resolves to
fallback
- The entire expression resolves to
Example
filename<req>, size:"full", align:"center", caption | :split(body, "|") => "Invalid image syntax"
filename<req>, size:"full", align:"center", caption | :split(body, "|") => "Invalid image syntax"
Behavior
| Case | Result |
|---|---|
| Valid input | Values are bound normally |
| Missing optional values | Defaults are applied |
Missing filename |
Fallback is used |
Equivalent Expansion
parts | :split(body, "|") filename | parts[0] size | parts[1] ?? "full" align | parts[2] ?? "center" caption | parts[3] ?? "" if filename.nix? return "Invalid image syntax" xx
parts | :split(body, "|") filename | parts[0] size | parts[1] ?? "full" align | parts[2] ?? "center" caption | parts[3] ?? "" if filename.nix? return "Invalid image syntax" xx
Binding Rules
Required (<req>)
filename<req>
filename<req>
- Must not be nix
- If nix → triggers fallback
Default (:)
size:"full"
size:"full"
- Used if value is nix
- Overrides implicit empty fallback
Unmarked Binding
caption
caption
If nix, becomes:
""
""
This is the implicit default.
Fallback (=>)
The => clause defines what happens when required bindings fail.
=> "<div>Bad input</div>"
=> "<div>Bad input</div>"
This can be:
- A value (used in output)
- An action (
:say, logging, etc.) - Any valid expression
Sheriff Rendering Example
filename<req>, size:"full", align:"center", caption | :split(body, "|") => """ <div class="sheriff-render-error"> Image cannot be processed because of missing required fields </div> """
filename<req>, size:"full", align:"center", caption | :split(body, "|") => """ <div class="sheriff-render-error"> Image cannot be processed because of missing required fields </div> """
If parsing fails, this HTML appears directly in the page.
Developer Feedback Example
x<req>, y<req> | coords => :say("You have to give all your numbers a value")
x<req>, y<req> | coords => :say("You have to give all your numbers a value")
- No crash
- No exception
- Controlled failure behavior
Multiple Required Fields
provider<req>, vid<req>, size:"full" | :split(body, "|") => "Invalid video"
provider<req>, vid<req>, size:"full" | :split(body, "|") => "Invalid video"
If any required binding is nix, fallback is used.
Provocation (Advanced)
Guarded destructuring ensures shape correctness.
If you need stricter guarantees (type, range, etc.), use provoke:
x<req>, y<req> | coords => "Bad input" :provoke(x > 0) :provoke(y > 0)
x<req>, y<req> | coords => "Bad input" :provoke(x > 0) :provoke(y > 0)
Destructuring handles presence.
provoke handles correctness.
Formatting Notes
Inline (preferred)
a<req>, b:"x", c | expr => fallback
a<req>, b:"x", c | expr => fallback
Tight form
a<req>,b:"x",c|expr=>fallback
a<req>,b:"x",c|expr=>fallback
Multiline fallback
a<req>, b | expr => """ Error: invalid input """
a<req>, b | expr => """ Error: invalid input """
How it differs
| Feature | Behavior |
|---|---|
| Destructuring | Assigns positional values |
<req> |
Enforces required bindings |
: |
Provides explicit defaults |
| Unmarked | Defaults to "" if nix |
=> |
Defines explicit failure resolution |
Why this exists
Goblin frequently works with structured text and dynamic output.
These require:
- strict shape enforcement
- safe defaults
- visible failures
- no silent breakage
Guarded Destructuring guarantees all of this in one expression.