I have stumbled upon interesting use case when length of array I return from proc depends on the type of the input argument. From language design perspective is it something Nim should support or no? Currently compiler crashes. I know it can be done with macro, more of conceptual discussion.
proc len(t: tuple|object): int =
for _ in fields(t):
inc len
proc fieldNames(t: tuple|object): array[len(t), string] =
var i = 0
for name,_ in fieldPairs(t):
result[i] = name
inc i
let tt = (a: 10, b: 20, c:30)
echo fieldNames(tt)
proc len(t: tuple|object): int =
for _ in fields(t):
inc len
Should this be
proc len(t: tuple|object): int =
for _ in fields(t):
inc result
Fieldnames still doesn't compile for me as written but len returns 3 with this change. Before changing, the compiler was trying to increment the len proc, reporting:
Error: type mismatch: got (proc (t: tuple or object): int | proc (w: WideCString): int{.noSideEffect, gcsafe, locks: 0.} | proc (x: TOpenArray): int{.noSideEffect.} | proc (x: string): int{.noSideEffect.} | proc (x: seq[T]): int{.noSideEffect.} | proc (x: array[I, T]): int{.noSideEffect.} | proc (x: cstring): int{.noSideEffect.})
but expected one of:
proc inc[T: Ordinal | uint | uint64](x: var T; y = 1)
If you want to use an array as a return type, instead of a seq "len(t)" should be a static[int] (so known at compile-time).
You can check andrea's linalg library on various static[int] examples in a matrix/vector context: https://github.com/unicredit/linear-algebra
Another thing is that using
let tt = (a: 10, b: 20, c:30)
means you're not dealing with compile time variables. This should be a const instead of a let.
Having said that, the compiler should (and normally does) state this. With the version I'm running, the compiler doesn't even throw an error, it just says Hint: test [processing] then silently quits. If you comment out the fieldNames proc compilation is as normal. I'm a bit out of date with devel though.
I see general perception that this code should compile of course if it depends only constant expressions. I will file yet another ticket at github issue tracker, using the following code as reproducible example:
proc len(T: typedesc[tuple|object]): static[int] =
var f: T
for _ in fields(f):
inc result
proc fieldNames(T: typedesc[tuple|object]): array[len(T), string] =
var i = 0
var f:T
for name,_ in fieldPairs(f):
result[i] = name
inc i
let tt = (a: 10, b: 20, c:30)
echo fieldNames(type(t))