"Concept" is that, but only for compile-time predicates and dispatch, i.e. for each call the routine to be called is determined at compile-time and will not change, at run-time it will be the same for a particular call each time. In contrast to methods, for which, depending on argumets passed, one or another concrete method is chosen at call-time.
Some illustration of concepts and how they are static:
type
# Just for illustration, some random concepts
HasInc = concept x
inc x
HasNotIncButHasAbs = concept x
x isnot HasInc
x.abs is x.type
var
i = 3
f = -5.0
c = 'a'
echo i is HasInc
echo i is HasNotIncButHasAbs
echo f is HasInc
echo f is HasNotIncButHasAbs
echo c is HasInc
echo c is HasNotIncButHasAbs
echo "_________________"
proc p(n: var HasInc) = # let's refer to it as `p1`
echo "p1 called; ", n, " has `inc`, calling it"
inc n
echo "now it's ", n
proc p(n: HasNotIncButHasAbs) = # let's refer to it as `p2`
echo "p2 called;", n, "'s absolute value is ", n.abs
p i # p1
p f # p2
p c # p1
echo "__________________"
# Really 2 concrete `pp` are created by the same name and with the same code,
# one always calling the 1st `p` (`p1`) and one always calling the 2nd (`p2`)
proc pp(n: var (HasInc or HasNotIncButHasAbs)) =
p n # No run-time choice here,
# for each instance of `pp` it's one of `p1` or `p2`, not any
pp i # calls the instance of `pp` which calls `p1`
pp f # this line calls another instance of `pp`, than the previous
pp c # the first one again
echo "__________________"
var a = [1.0, 2.0, 3.0]
for i in a.mitems:
p i # `p2` for each iteration; you may not refer here to different `p`,
# except if they are `method`s (or you can manually dispatch with `if`s)
echo "__________________"
# ========================================================= #
# What concepts cannot (needs run-time choice),
# of what may be supposed by "predicate dispatch".
# The code below won't work.
#type
# X = concept x
# x < 10
# Y = concept y
# y >= 10
#proc q(n: X) = echo "X ", n
#proc q(n: Y) = echo "Y ", n
#
#var n = 5
#q n
#n = 50
#q n
Well, I tried add condition statement in the multi-method and found it worked very well, and here is my tiny view dispatch framework!:
type
Document = ref object of RootObj
text: string
Request = ref object of RootObj
reqMethod: string
method view(doc: Document, req: Request): string {.base.} =
if req.reqMethod=="GET":
return doc.text
let doc = Document(text: "Hello World!")
echo view(doc, Request(reqMethod: "GET"))
Some people said closure is poor-man object/method, but I disagree, IMHO object/method is poor emulation for closure .
in my case, I never found method as much useful as closure, maybe it's just because I don't have that vast experience tho