I tried 4 different ways, 2 fails, 2 works.
Using a proc as a generic (failure):
type
BinaryTree[V; compare: proc(a, b: V): bool] = object
value: V
proc insert[V; compare](tree: BinaryTree[V, compare], value: V): bool =
# Error: attempting to call routine: 'compare'
# found 'insert.compare [declared in
/home/beta/Programming/Nim/Arraymancer/build/bintree.nim(5, 16)]' of kind 'type'
compare(value, tree.value)
var a = BinaryTree[int, proc(a, b: int): bool = a < b](value: 10)
echo insert(a, 20)
Run
Using a proc as a static (failure):
type
BinaryTree[V; compare: static proc(a, b: V): bool] = object
# Error: cannot generate VM code for proc (a, b: V): bool
value: V
proc insert[V; compare](tree: BinaryTree[V, compare], value: V): bool =
compare(value, tree.value)
var a = BinaryTree[int, proc(a, b: int): bool = a < b](value: 10)
echo insert(a, 20)
Run
Using a compile-time switch (success):
type
CmpKind = enum
GreaterThan
LowerThan
BinaryTree[V; cmp: static CmpKind] = object
value: V
proc insert[V; cmp](tree: BinaryTree[V, cmp], value: V): bool =
when cmp == GreaterThan:
value > tree.value
elif cmp == LowerThan:
value < tree.value
var a = BinaryTree[int, LowerThan](value: 10)
echo insert(a, 20)
Run
Using a compile-time dispatch table (success):
import macros
type
CmpKind = enum
GreaterThan
LowerThan
BinaryTree[V; cmp: static CmpKind] = object
value: V
let funcTable {.compileTime.} = [
GreaterThan: ident">",
LowerThan: ident"<"
]
macro dispatch(a: typed, cmp: static CmpKind, b: typed): untyped =
result = newCall(funcTable[cmp], a, b)
proc insert[V; cmp](tree: BinaryTree[V, cmp], value: V): bool =
dispatch(value, cmp, tree.value)
var a = BinaryTree[int, LowerThan](value: 10)
echo insert(a, 20)
Run