Seemingly this last issue may be bypassed with a macro.
    
    
    type
      BinaryTree[V; compare: static[untyped]] = object
    
    # different ways of providing a procedure
    # an `echo` is added to each of them, to distinguish
    
    const less1 = proc(a, b: int): bool = (echo 1; a < b)
    type T1 = BinaryTree[int, less1]
    var tree1: T1
    
    const less2 = proc(a, b: int): bool = (echo 2; a < b)
    var tree2: BinaryTree[int, less2]
    
    proc less3(a, b: int): bool = (echo 3; a < b)
    type T3 = BinaryTree[int, less3]
    var tree3: T3
    
    proc less4(a, b: int): bool = (echo 4; a < b)
    var tree4: BinaryTree[int, less4]
    
    var tree5: BinaryTree[int, proc(a, b: int): bool = (echo 5; a < b)]
    
    import macros
    # the macro can be just one line, if to restrict to just one of formats 
above
    macro compare(v: typed): auto =
      var p=v.getImpl[1]
      if p.kind == nnkSym:
        p = p.getImpl
        expectKind p, nnkTypeDef
        expectKind p[2], nnkBracketExpr
        expectKind p[2][2], nnkSym
        p = p[2][2]
      else:
        p = p[2]
        if p.kind == nnkSym:
          p = p.getImpl
        else:
          p = p[0]
      if p.kind == nnkProcDef:
        p = p[0]
      p
    
    # testing
    var n = 20
    echo compare(tree1)(n, 30)
    echo compare(tree2)(n, 30)
    echo compare(tree3)(n, 30)
    echo compare(tree4)(n, 30)
    
    
    Run

(Another issue, only for the first kind (`const` \+ `type`), if n in the 
example is a constant or is replaced with a literal, that is the procedure may 
be evaluated at compile-time, then it is (the side-effect will occur at 
compile-time, for pure functions there's no difference).)

Reply via email to