I can declare a proc to return a "union type", but cannot actually return values of more than one type:
proc test(b: bool) : int|string =
if b: 1 else: "hello"
echo test true
echo test false
Expected:
1 > hello
Actual:
Error: type mismatch: got 'string' for '"hello"' but expected 'int literal(1)'
Even if I swap the return types (string|int) the error is the same. I am only allowed to return an int. I tried putting the return type in parens; and I tried using or instead of |. No dice.
What am I missing? (I don't want to use a variant object.)
Nim does not have "product" types. (string|int) is a "typeclass" in nim speak and only used for generics: https://nim-lang.org/docs/manual.html#generics-type-classes
Nim is statically typed, therefore the return type has to be known at compile-time. Your only choice here is a variant object (or rethinking your design).
I see. Thank you.
I find variant objects to be unnecessarily clunky to use, though. Specifically the requirement that each variation must specify a different property name for its content.
if string|int is not a valid return type
string | int is a valid return type, in particular in your case if you know statically the boolean you can use this (which is a valid alternative to the variant where you assume you know stuff at compile time):
proc test(b: static[bool]) : int|string =
when(b): 1
else: "hello"
echo test true
echo test false
shouldn't the compiler emit an error
it does emit the error: Error: type mismatch: got 'string' for '"hello"' but expected 'int literal(1)'. Since the function test is a generic (the return type being a type class means that for every return type a new proc will be generated), the specific proc is generated when it is instantiated. This happens when you call echo test true and in that case the compiler realizes that the generic proc definition is not valid (in principle in this case it could have realized it earlier but it is not true in general) and throws the correct error: the if expression has int as first expression returned, so all other branches must have an int, I am expecting an int (which I derived being an int from a literal 1), and now I find an "hello"
But this is a valid return type, provided the actual return type is known at compile time.
This is valid and the result is what you expect:
proc test(x: static bool): string | int =
when x:
1
else:
"hello"
echo test true
echo test false
I see. The situation is clearly more complex than I realised. I will look into statics further.
Thank you for explaining.