How should Result values be accessed safely using guard expressions?
← Data Flow Safety · Ref: Q687
Result values must be accessed through guard expressions that ensure the success or error case is properly checked before use.
GUARD ACCESS PATTERN (E08030)
The correct way to access a Result is through a guard:
if result.isOk() okValue <- result.ok() process(okValue)
Accessing the result value outside a guard risks using an error value as if it were a success, triggering E08030.
SAFE DEFAULT PATTERN
The simplest approach uses okOrDefault:
safeValue <- result.okOrDefault(fallback)
This always returns a usable value without risk.
NO REASSIGNMENT IN GUARD (E08040)
Once a guard variable is bound, it cannot be reassigned within the guard block. The variable is a one-time extraction.
See Q634 for guard expressions. See Q636 for chained guards. See Q306 for Result type basics.
Example
defines module qa.dataflow.resultguard defines constant DEFAULT_AGE <- 0 UNKNOWN_LABEL <- "unknown" defines function <?- Function returning a Result. Demonstrates producing success and error cases. -?> parseAge() as pure -> ageText as String <- parsed as Result of (Integer, String): Result(Integer(), "no input") if ageText? parsed: Result(Integer(ageText), String()) <?- Correct: use okOrDefault for simple safe access. No guard needed when a default is acceptable. -?> getAgeOrDefault() as pure -> ageText as String <- ageValue as Integer: DEFAULT_AGE result <- parseAge(ageText) ageValue: result.okOrDefault(DEFAULT_AGE) <?- Correct: use isOk() guard before accessing ok(). Check and access in the same syntactic scope. -?> describeAge() -> ageText as String <- description as String: UNKNOWN_LABEL result <- parseAge(ageText) if result.isOk() actualAge <- result.ok() description: `Age: ${actualAge}` defines program ResultGuardAccessDemo() stdout <- Stdout() stdout.println(`Default: ${getAgeOrDefault("25")}`) stdout.println(`No input: ${getAgeOrDefault("")}`) stdout.println(describeAge("30")) stdout.println(describeAge(""))
Common mistakes
E50060 — String has no toUpperCase() method in EK9. Use upperCase() instead. See ek9 -h E50060 for details.
Incorrect:
stdout.println(describeAge("30").toUpperCase())
Correct:
stdout.println(describeAge("30"))
E50060 — Integer has no intValue() method in EK9. Integer values are used directly. See ek9 -h E50060 for details.
Incorrect:
ageValue: result.okOrDefault(DEFAULT_AGE).intValue()
Correct:
ageValue: result.okOrDefault(DEFAULT_AGE)
Other ways to ask this
- What is E08030 result value accessed outside guard?
- What is E08040 result guard reassignment?
- How do I safely unwrap a Result in EK9?
- What is the correct pattern for Result guard access?
Coming from another language?
Java: Optional.ifPresent() or manual null checks. Rust: match on Result with Ok/Err. Go: explicit error return values (val, err). Python: try/except. EK9: guard expressions with isOk()/isError() or okOrDefault() with compile-time enforcement.
Keywords: access, E08040, E08030, unwrap, safety, initialize, null-safe, ok, guard, data-flow, error, safe, result, isset