I can't figure out why the following overloaded procs work:
import
sequtils
proc newSeq2d*[int](x, y: int): seq[int] =
result = newSeq[int]((x * y) + 1)
result[0] = x
proc newSeq2d*[uint8](x, y: int): seq[uint8] =
result = newSeq[uint8]((x * y) + 3)
result[0] = (x and 0xff0000).uint8
result[1] = (x and 0x00ff00).uint8
result[2] = (x and 0x0000ff).uint8
but switching the parameters to Natural type:
proc newSeq2d*[int](x, y: Natural): seq[int] =
and proc newSeq2d*[uint8](x, y: Natural): seq[uint8] =
gives
Error: redefinition of 'newSeq2d'
.
Does anyone have any ideas?
Possible workaround:
import
sequtils
proc newSeq2d*[T: int](x, y: Natural): seq[T] =
result = newSeq[int]((x * y) + 1)
result[0] = x
proc newSeq2d*[T: uint8](x, y: Natural): seq[T] =
result = newSeq[uint8]((x * y) + 3)
result[0] = (x and 0xff0000).uint8
result[1] = (x and 0x00ff00).uint8
result[2] = (x and 0x0000ff).uint8
let x = newSeq2d[int](10, 10)
I don't know why this happens, but it may be a clue. I didn't know that what you are doing (using the generics syntax without a type parameter) was even valid.Yeah, even keeping the return signature the same, and just adding the [T: int] and [T: uint8] to newSeq2d fixes the compilers complaint, and works fine with the rest of what I was doing, so thanks for that!
But yeah, I don't get why that would fix it, heh.
It's because when you write [int], int is actually the name of a type parameter, it's not the built-in int type. It's just like you had written an unbound type parameter [T].
To prove this to yourself, try running:
import typetraits
proc foo[int]() =
echo $type(int)
foo[string]()
It will print string since [int] gets bound to string.
So without type constraint such as [T: int], both of your procs have the same type signature, hence the compile failure.
That makes sense, and explains why using T: int / T: uint8 is correct, but there is still something wierd going on because if I use int for the parameters it compiles fine, it is only if I use Natural that it fails,.
Also, the int and uint8 must be more than simple symbols, because if I use a different symbol, and try to call one of the procs, it can't differentiate between the two, and won't compile:
import
sequtils
proc newSeq2d*[a](x, y: int): seq[int] =
result = newSeq[a]((x * y) + 1)
result[0] = x
proc newSeq2d*[a](x, y: int): seq[uint8] =
result = newSeq[a]((x * y) + 4)
result[0] = (x and 0xff000000).uint8
result[1] = (x and 0x00ff0000).uint8
result[2] = (x and 0x0000ff00).uint8
result[3] = (x and 0x000000ff).uint8
var a: newSeq2d[int](2,3)
Edit: Actually this does make sense, since the return type will actually be an int or uint8 now. But on the other hand, shouldn't the differing return type allow for the procs to be distinguished?
If I do use int/uint8 as I did, the uint8 proc is called regardless of the type I am using, so in that sense the uint8/int are acting as simple symbols, and not allowing type differentiation:
import
sequtils
proc newSeq2d*[int](x, y: int): seq[int] =
echo "int!"
result = newSeq[int]((x * y) + 1)
result[0] = x
proc newSeq2d*[uint8](x, y: int): seq[uint8] =
echo "uint8!"
result = newSeq[uint8]((x * y) + 4)
result[0] = (x and 0xff000000).uint8
result[1] = (x and 0x00ff0000).uint8
result[2] = (x and 0x0000ff00).uint8
result[3] = (x and 0x000000ff).uint8
var a: seq[uint8]
a = newSeq2d[uint8](2,3)
var b: seq[int]
b = newSeq2d[int](2,3)
So clearly the T: is necessary for what I want, but somehow the compiler is being fooled into thinking the signatures are different, even though they aren't really.
@boia01:
It's because when you write [int], int is actually the name of a type parameter, it's not the built-in int type.
Hah! Good catch. This possibility never occurred to me because I never realized Nim allows you to use type names as normal identifiers.
let int: int = 123
echo int
That is strange...@nucky9:
somehow the compiler is being fooled into thinking the signatures are different, even though they aren't really.
They actually are different. It's easier to see if you fix the confusing naming.
proc newSeq2d*[T](x, y: T): seq[T]
proc newSeq2d*[T](x, y: int): seq[T]
Now, with Natural, this is what you get:
proc newSeq2d*[T](x, y: Natural): seq[T]
proc newSeq2d*[T](x, y: Natural): seq[T]