Hello!
I'm quite new to nim and I have a question regarding concepts. I'm trying to create a concept for a simple tree. However, I'm having a confusing issue.
How come this compiles:
type TreeNode* = concept t
t.children is seq[type t]
proc isRootNode*(self: TreeNode): bool =
true
type Numbers = ref object
children: seq[Numbers]
let numTree = Numbers()
doAssert numTree.isRootNode()
But this does not:
type TreeNode* = concept t, type T
t.children is seq[T] # Use 'T' instead of 'type t'
proc isRootNode*(self: TreeNode): bool =
true
type Numbers = ref object
children: seq[Numbers]
let numTree = Numbers()
doAssert numTree.isRootNode()
It produces this error with the explain pragma:
Error: type mismatch: got <Numbers>
but expected one of:
proc isRootNode(self: TreeNode): bool
first type mismatch at position: 1
required type for self: TreeNode
but expression 'numTree' is of type: Numbers
****\tree.nim(11, 10) template/generic instantiation of `doAssert` from here
****\treelib.nim(8, 5) TreeNode: concept predicate failed
expression: isRootNode(numTree)
Why is the Numbers object not considered to be a TreeNode in the second case even though (I think) it fulfills the concept requirements?
By default, the compiler will report the matching errors in concepts only when no other overload can be selected and a normal compilation error is produced. When you need to understand why the compiler is not matching a particular concept and, as a result, a wrong overload is selected, you can apply the explain pragma to either the concept body or a particular call-site.
This will provide Hints in the compiler output either every time the concept is not matched or only on the particular call-site.type MyConcept {.explain.} = concept ... overloadedProc(x, y, z) {.explain.}
Looks like you have to use typedesc T. Not sure if that's a bug or not:
type TreeNode* = concept t, type T
t.children is seq[typedesc T]
proc isRootNode*(self: TreeNode): bool =
true
type Numbers = ref object
children: seq[Numbers]
let numTree = Numbers()
doAssert numTree.isRootNode()