# Generic version
func toArray[S: static string, T](): array[S.len(), T] {.compileTime.} =
var i = 0
for c in S:
result[i] = c.T
i.inc()
# static parameter version
func toArray[T](str: static string): array[str.len(), T] {.compileTime.} =
var i = 0
for c in str:
result[i] = c.T
i.inc()
Why does static parameter version gives me an error?
If you break it down further
func toArray(str: static string): array[str.len(), char] =
var i = 0
for c in str:
result[i] = c
inc i
(This also doesn't work just for illustration) This is a single function, with the return value set as array[0,char]
Since there's only one instantiation of the function, what else could the length of the array be?
You need a generic, instantiated based on the length of that string
func toArray[L:static int](str:string):array[L,char]
Would work, even, but your way is clearly better. Why does static parameter version gives me an error?
There's no technical reason for that, IMHO it's a bug. The manual states that a static parameter is implicitly generic and that its value has to be a constant, i.e. can be evaluated at compile time. If we force that with a static cast like this
func toArray[T](str: static string): array[static[int](str.len()), T] =
var i = 0
for c in str:
result[i] = c.T
i.inc()
the compiler tells us that
Error: cannot evaluate at compile time: str
which is a lie.
I hope somebody can explain to me why I'm wrong about this, because that would be much better than the half-informed general impression of Nims type parametrization I have now:
There are four different kinds of compile-time type parametrization, if I count correctly: generics, static parameters, typedesc parameters and concepts. Of those, two are somewhat broken (static parameters and concepts), one is almost not broken (generics) and one is a slightly weird replacement for a type symbol (typedesc). And some of them tend to collide in unpredictable ways.
If something can stop the languages' success, it's that mess.
If something can stop the languages' success, it's that mess.
Apparently the utter lack of generics, static, typedesc, concepts didn't prevent Go success ;).
Also you forgot distinct
That said, unfortunately all those were not designed from the get go but grew organically. For example the semcheck.nim and sigmatch.nim files are now extremely complex and I have mentioned a couple time how it's easy to suddenly feel like you stumbled into an abandoned city when working with those, especially in macros.
Apparently the utter lack of generics, static, typedesc, concepts didn't prevent Go success ;).
Yes, because people know what they get. Having a bunch of features with overlapping problem domains implemented inconsistently is not a better deal for everyone.
Also you forgot distinct
It's like shopping without a list: the only thing I can be sure of is that I will forget something ..
For example the semcheck.nim and sigmatch.nim files ...
Are those the ones giving me a headache when I try to create new types from existing types with macros? Trying to understand the rules by trial-and-error turned out to be quite a time sink. Maybe we need a list of things not to try without understanding the compiler source.
Are those the ones giving me a headache when I try to create new types from existing types with macros? Trying to understand the rules by trial-and-error turned out to be quite a time sink. Maybe we need a list of things not to try without understanding the compiler source.
Likely since most problems I mentioned in https://github.com/nim-lang/Nim/issues/8677 and https://github.com/nim-lang/RFCs/issues/44 are those modules.
just noticed that my posts sound more cynical than intended. I really like Nim and have great respect for the people creating it. But sometimes when I try more complex things, my enthusiasm is strangled by non-orthogonal quirkiness and it gets frustrating.
You are not alone. Though diligently expanding those lists helps.