Presence Guards
- with runs when an optional is present; without runs when it is absent.
- Use as name for a readable non-optional binding, or use the implicit it binding.
- An else branch handles the opposite state and may bind the present value after without.
With: Run When Present
1with expense.note as note {2 label = note.trim()3}Inside the block, the binding has the unwrapped non-optional type. A named binding is clearer when the block has more than one statement or when nested scopes also use it.
Without: Run When Absent
1without expense.note {2 expense.note = "No receipt note"3}without is useful for initialization, required-value diagnostics, and fallback actions that take more than one expression.
Handling Both Paths
1with expense.receipt as receipt {2 label = receipt.name3} else {4 label = "No receipt"5}After without, the else path is the present path and may bind the value with as name. Keep the branch that reads most naturally for the decision you are expressing.
Guarding Indexed Values
1with expenses[0] as first_expense {2 selected = first_expense3}45with balances[member_id] as amount {6 current_balance = amount7}Normal array and map indexes are optional, so the same guard syntax proves a position or key exists before using the value.
Narrowing Scope And Reassignment
- The narrowed binding exists only inside its branch.
- The original expression remains optional outside the guard.
- Prefer a named binding if the original path may be assigned inside the block.
- Do not assume a previous guard proves presence after unrelated mutation or outside its scope.
Choose A Guard Or Coalesce
| Need | Use |
|---|---|
| One expression with a fallback | value ?? fallback |
| Several statements when present | with value as present { ... } |
| Several statements when absent | without value { ... } |
| Different work for both paths | Add else. |
| Read an optional as required without proof | Do not; guard or coalesce first. |
Common Mistakes
| Mistake | Correction |
|---|---|
| Read a field from an optional directly | Narrow it with with first. |
Use without as a presence branch | Use with for the present value. |
| Use a guard binding after its block | Keep narrowed access inside the guard scope. |
| Use a multi-statement guard for one fallback expression | Prefer ?? for the simple case. |
