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)

2017-05-17 09:38:57

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)

2017-05-17 10:07:59

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

2017-05-17 10:17:04

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.

2017-05-17 10:59:59

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))

2017-05-17 16:43:35