return inside a value-producing matchWhat it means. A match expression is used as a value — assigned to a variable, returned as an expression, or passed as an argument — and one of its branches ends with a bare return (a return with no value).
package main
import "os"
import . "martianoff/gala/std"
func run(path string) {
val data = Try(os.ReadFile(path)) match {
case Success(b) => string(b)
case Failure(err) => {
Println(s"error: ${err.Error()}")
return // bare return in a value-producing branch
}
}
Println(data)
}
error[GALA-E0015]: bare `return` inside a match branch whose result is used as a value
--> e0015.gala:7:16
|
7 | val data = Try(os.ReadFile(path)) match {
| ^^^ the match is wrapped in a function that must return string
|
= hint: the match is wrapped in a function that must return string; restructure to early-exit before the match, or use combinators like .Recover / .GetOrElse. See docs/errors/GALA-E0015.md
The caret marks the match being used as a value, and the hint names the result type its wrapper must produce.
A match-as-value lowers to an immediately-invoked function expression:
data := func(obj ...) string {
switch ... {
case Success: return string(b)
case Failure: fmt.Println(...); return // invalid: must return string
}
}(...)
A bare return there does not exit the enclosing function — it exits the wrapper. Because the wrapper has a non-void return type, Go rejects it with “not enough return values”.
1. Early-exit before the match. Handle the failure first, then destructure the success case:
func run(path string) {
val result = Try(os.ReadFile(path))
if (result.IsFailure()) {
Println(s"error: ${result.GetError().Error()}")
return
}
Println(string(result.Get()))
}
2. Use combinators. Map, Recover, and GetOrElse avoid the wrapper entirely:
func run(path string) {
val data = Try(os.ReadFile(path))
.Map((b) => string(b))
.GetOrElse("")
if (data == "") { return }
Println(data)
}
3. Make the match the function body. When the match is the function’s result, each branch legitimately returns a value.
GALA’s match-as-value form has expression semantics: every branch must contribute a value of the match’s result type. A bare return is a statement-level control-flow operation whose scope — outer function or enclosing wrapper — is ambiguous. Rather than silently pick one reading and generate surprising Go, the transpiler rejects the construct and points at the explicit rewrites.
Try, Option, and Either combinators