Hey everyone,
I’m currently building a 2D game engine in Odin. Coming from a Go background, my default error-handling pattern for procedures is returning (Value, ok: bool)—or just ok: bool for simple checks.
In Go, I was used to reusing err across multiple calls in the same scope using short variable declarations (:=), as long as at least one new variable was being declared on the left side:
`Go// Valid Go code
val1, err := stepOne()
if err != nil { return err }
val2, err := stepTwo() // Reuses ‘err’ because val2 is new
if err != nil { return err }`
However, in Odin, trying a similar pattern throws a variable shadowing error because Odin strictly forbids re-declaring identifiers in the same scope with :=:
`Fragment kodu//
Odin Compiler Error: Variable shadowing / ‘ok’ already declared
val1, ok := my_proc()
if !ok do return
val2, ok := my_proc()
if !ok do return`
I understand why Odin prevents variable shadowing (to eliminate a huge class of subtle bugs), but working around it raised a few questions for me regarding idiomatic Odin design:
1. Re-using variables with = vs :=
If a procedure returns only ok: bool, pre-declaring ok once and reusing it with = is simple and clean:
`Fragment kodu// Pre-declaring works great for single-value returns:
ok: bool
ok = simple_check_one()
if !ok do return
ok = simple_check_two()
if !ok do return`
However, if procedures return multiple values (e.g., (Texture, i32, i32, bool)), using = requires pre-declaring all the variables upfront just to avoid shadowing ok. Adding call-site logging to each check quickly gets verbose:
`Fragment kodu// Works, but pre-declaring everything just to log at the call-site gets verbose:
tex1, tex2: ^sdl2.Texture
w1, h1, w2, h2: i32
ok: bool
tex1, w1, h1, ok = load_texture(“player.png”)
if !ok {
log.error(“Failed to load player texture at startup”)
return
}
tex2, w2, h2, ok = load_texture(“enemy.png”)
if !ok {
log.error(“Failed to load enemy texture at startup”)
return
}`
2. The or_return logging trade-off
If I use or_return to avoid managing the ok variable altogether, it stays very clean:
Fragment kodutex1, w1, h1 := load_texture("player.png") or_return tex2, w2, h2 := load_texture("enemy.png") or_return
However, using or_return means I can’t easily print a contextual log message at the callsite on failure before returning. It seems to force a design where leaf procedures are expected to log errors internally, while parent procedures focus purely on control flow.
My Questions for the Community:
- Is pushing log responsibility down to leaf procedures (or using
context.logger) the intentional design philosophy when leaning intoor_return? - What is the most idiomatic way in Odin to handle sequential multi-value
(Value, bool)calls when you do want to log contextual details at the callsite without creating deeply nested code or pre-declaring heaps of variables?
Thanks!