This idea has been nagging me at the back of my head. I was thinking of writing up an RFC, but don't want to waste my time if this has already been thought of before or if it presents more problems than it provides benefits for.
The idea: rather than requiring an API to have an explicit out parameter in a proc (e.g. for performance benefits), the special result variable could serve as an out parameter at the call site for every proc. At the callsite the result variable can be provided via a keyword argument. There is some ambiguity here: do we overwrite the user's result variable or "append" to it (e.g. if it is a container, to re-use pre-existing allocated memory).
Append is most useful convention here (IMO). The append coding convention would require implementations to rely on the default initialization (T.default) instead of an explicit initialization of result as I see in some Nim code in the wild.
Using pixie as an example:
Currently:
var p = parsePath(segA)
p.addPath(parsePath(segB)) # temp Path constructed from parsePath(segB)
With this idea:
var p2 = parsePath(segA)
parsePath(segB, result = p2) # no temp path & parsePath now does NOT return a Path
In the "Current" code p.addPath performs a .add's on the underlying seq storing path commands, see here
RVO might optimize the temporary out in the "current" code and optimize it to look like the "With the idea" code, but I think the intent is more clear with this language design idea.
The implementation of parsePath would have to change from:
proc parsePath*(path: string): Path {.raises: [PixieError].} =
## Converts a SVG style path string into seq of commands.
result = newPath()
...
to:
proc parsePath*(path: string): Path {.raises: [PixieError].} =
## Converts a SVG style path string into seq of commands.
# assume result is initialized
...
Note in this case, proc newPath*() = Path() (see), i.e. Path.default
Potential problems or reasons to be against this idea:
What are your thoughts? Has this been thought of before?