result return [language.result]
Avoid using result for returning values.
Prefer expression-based return or in some cases, explicit return
Pros
- Recommended by NEP-1
- Used in standard library
- Saves a line of code avoiding an explicit
vardeclaration - Accumulation-style functions that gradually build up a return value gain consistency
Cons
- No visual (or compiler) help when a branch is missing a value, or overwrites a previous value
- Disables compiler diagnostics for code branches that forget to set result
- Risk of using partially initialized instances due to
resultbeing default-initialized- For
reftypes,resultstarts out asnilwhich accidentally might be returned - Helpers may accidentally use
resultbefore it was fully initialized - Async/await using result prematurely due to out-of-order execution
- For
- Partially initialized instances lead to exception-unsafe code where resource leaks happen
- RVO causes observable stores in the left-hand side of assignments when exceptions are raised after partially modifying
result
- RVO causes observable stores in the left-hand side of assignments when exceptions are raised after partially modifying
- Confusing to people coming from other languages
- Confusing semantics in templates and macros
Practical notes
Nim has 3 ways to assign a return value to a function: result, return and "expressions".
Of the three:
- "expression" returns guarantee that all code branches produce one (and only one) value to be returned
- Used mainly when exit points are balanced and not deeply nested
- Explicit
returncan simplify conditional expressions- Used to avoid deep nesting and early exit, above all when returning early due to errors
resultis used to accumulate / build up return value, allowing it to take on invalid values in the interim- the usage of
resultis sometimes necessary to aid the compiler in Return-Value-Optimization analysis - if this is the case, useresultbut report a bug
Multiple security issues, nil reference crashes and wrong-init-order issues have been linked to the use of result and lack of assignment in branches.
In general, the use of accumulation-style initialization is discouraged unless made necessary by the data type - see Variable initialization - this also applies to the implict result variable.