Here's an example of concepts and generics extracted from a Nim project. It defines an Eq concept and tries to implement that concept for an arbitrary 2-tuple:
import sugar
# Handy type for a relation as Nim proc.
type Relation*[T, U] = proc (x: T, y: U): bool
# A simple equality concept
type Eq* = concept x, y
eq(x, y) is bool
# Nim ints implement Eq
proc eq*(x, y: int): bool = x == y
# Helper function to apply a relation to two tuples. Always true for now.
proc check_all*[T, U](fn: Relation[T, U], xs: (T, T), ys: (U, U)): bool =
true
# Let 2-tuples implement Eq if their items do.
proc eq*[T: Eq, U: Eq](xs: (T, T), ys: (U, U)): bool =
# This compiles.
#check_all((x: T, y: U) -> bool => eq(x, y), xs, ys)
# This doesn't compile.
check_all(eq, xs, ys)
The line check_all(eq, xs, ys) causes a compilation error about instantiating the type T. Promoting that use of eq to a proc with check_all((x: T, y: U) -> bool => eq(x, y), xs, ys) however does compile.
I'm thinking that the proc argument and parameter in check_all have different calling convention pragmas? By wrapping eq in a proc the pragmas do match up? If that is the case what's an idiomatic set of pragmas to attach to the Relation type and the proc parameters in check_all?
I understand I could create a macro that generates code using https://nim-lang.org/docs/iterators.html#fields.i,S,T, for this, but I'd like to understand better what is going wrong here with my generic types and pragmas.
The default calling convention for a procedure written in a type field is a {.closure.} so to support what you want you'll want to annotate with {.nimcall.} that way it is compatible with top level procedures. Calling conventions can be seen here . If you want more helpful error messages I can suggest using a recent devel version of the compiler to get them. An example of those new error below:
tproc_mismatch.nim(43, 8) Error: type mismatch: got <proc (){.inline, noSideEffect, gcsafe, locks: 0.}> but expected 'proc (){.closure.}'
Calling convention mismatch: got '{.inline.}', but expected '{.closure.}'.
tproc_mismatch.nim(48, 8) Error: type mismatch: got <proc (){.locks: 0.}> but expected 'proc (){.closure, noSideEffect.}'
Pragma mismatch: got '{..}', but expected '{.noSideEffect.}'.
That's an excellent suggestion to use the devel compiler. Those error messages are much more informative that what I'm seeing.
Cloning the source (devel is the default branch) and running the build_all.sh should be enough to build a devel version on macOS? I seem to get quite different error messages from the above on my devel? build.