I've bumped into the following subtlety and was wondering if anyone could help me clarify it. Why does the following fails to compile:
proc aProc*(): int =
try:
1
except Exception as exc:
echo "oops"
# Fails with "Error: expression '1' is of type 'int' and has to be used (or discarded)"
but this doesn't:
proc aProc*(): int =
try:
return 1
except Exception as exc:
echo "oops"
# prints 1
and neither does this?
proc aProc*(): int =
try:
1
except Exception as exc:
2
# prints 1
That's because of implicit returns. Procedures will implicitly return the last statement. Try blocks (and most other blocks) will also return their last statement. Of course each branch has to return the same type, Nim is strictly typed after all. Combining this knowledge we can look at your snippets. The first snippet fails because only of the branches in the try statement has a return value. The error isn't great, but it tries to tell you that there is a value somewhere where one isn't expected. The second snippet works because now we're explicitly returning from the good path, no longer relying on the implicit return. The last snippet works because both branches now return the same type, and the try block can therefore be returned implicitly from the proc. Note that here you could have the echo statement in the except branch, just before the 2.
For more information I wrote this article a while back: https://peterme.net/tips-and-tricks-with-implicit-return-in-nim.html
Thanks for the reply, guys. I think the part that confused me is that proc aProc(): T will happily return default(T) in case the return value is undefined by the end of its execution, as in, for instance:
proc aProc*(): auto =
if false:
return 1
# returns default(int) = 0
I assumed this would be a property of any block; i.e., if one of the paths is undefined then it'd just evaluate to default(K), where K is the type inferred from the paths that actually have an evaluation type defined. But I guess that's not the way it works.