Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is nim type definition for generic procedure?

Tags:

nim-lang

I have a strategies expressed as generics in nim:

proc fooStrategy[T](t: T, ...)
proc barStrategy[T](t: T, ...)

I would like to create a lookup table for the strategies by name... so I tried:

type
  Strategy*[T] = proc[T](t: T, ...)

let strategies* = toTable[string, Strategy[T]]([
  ("foo", fooStrategy), ("bar", barStrategy)])

This doesn't work -- the type declaration fails. If I were to get by that I could guess that the table of strategies would also have problems. Is there another way to do this? "T" is supposed to be "some 1D collection type" -- could be sequence, array, vector from blas, etc. I could add concrete strategies to the table for common collections, but I still have the problem with the function pointer, as

type
  Strategy* = proc(t: any, ...)

let strategies* = toTable[string, Strategy]([
  ("foo-seq[int]", fooStrategy[int]), ...])

still has problems. Any suggestions?

like image 363
shaunc Avatar asked Apr 29 '16 05:04

shaunc


1 Answers

There are multiple issues with your code:

Firstly, initTable does not take a list of items for the table. It only takes an initial size. You want to use toTable instead.

Secondly, you must explicitly set a value for the generic parameter T when creating a table, because at runtime, all generic parameters must be bound to a type.

Thirdly, the proc types have to exactly match, including pragmas on the proc. This one's tricky.

Here is a working example:

import tables

type
  Strategy*[T] = proc(t: T) {.gcsafe, locks: 0.}

proc fooStrategy[T](t: T) = echo "foo"
proc barStrategy[T](t: T) = echo "bar"

let strategies* = toTable[string, Strategy[int]]([
    ("foo", fooStrategy[int]), ("bar", barStrategy[int])
])

For this example, I create a table with Strategy[int] values (you cannot have a table with Strategy[T] values as this is not a concrete type). I instantiate both fooStrategy and barStrategy with [int] to match the table type. I added {.gcsafe, locks: 0.} to the type definition. If this is omitted, you will get a compiler error:

test.nim(9, 49) Error: type mismatch: got (Array constructor[0..1, (string, proc (t: int){.gcsafe, locks: 0.})])
but expected one of:
proc (pairs: openarray[(string, Strategy[system.int])]): Table[system.string, Strategy[system.int]]{.gcsafe, locks: 0.}

As you see, the compiler tells you in the first line what it sees and in the third line what it expects. it sees procs with {.gcsafe, locks: 0.} because those pragmas are implicitly assigned to the procs defined above. The pragmas change the type, so to be able to assign those procs to Strategy[T], you have to define the same pragmas to Strategy[T].

like image 181
flyx Avatar answered Nov 10 '22 08:11

flyx