I tried the following code but cannot compile because there are 2 procs named "f". But the function specifies the type of argument f. Also, if the second definition of proc f is commented out, it can be compiled. It can also be compiled if the arg g to be non-static in the definition of eval, like the comment, it can be compiled although there are two procs f.
Then, how to do it in the static case? My inconvenient solution for now is to only change the name f to f0, f1.
proc f(a, b:int):int = a + b
proc f(a:int):int = a
proc eval(a, b:int, g:static[proc(a, b:int):int]):int =
let g = g
g(a, b)
#proc eval(a, b:int, g:proc(a, b:int):int):int =
# g(a, b)
echo eval(3, 4, g = f)
Nim's type conversions on procs do work to disambiguate, it's a rather ugly syntax and somewhat obscure, but it works:
proc f(a, b:int):int = a + b
proc f(a:int):int = a
proc eval(a, b:int, g: static[proc(a, b:int):int]):int =
let g = g
g(a, b)
echo eval(3, 4, (proc(a, b: int): int)(f))
Thank you very much!!
Based on @ElegantBeef 's code, I more more non-ugly way which can call with out conversion. I first tried it by template but failed. Then, I used macro.
import macros
proc f(a, b:int):int = a + b
proc f(a:int):int = a
proc evalImpl(a, b:int, g:static[proc(a, b:int):int]):int =
let g = g
g(a, b)
#proc eval(a, b:int, g:proc(a, b:int):int):int =
# g(a, b)
macro eval(a, b:int, g):untyped =
quote do:
evalImpl(`a`, `b`, (proc(a, b:int):int)`g`)
echo eval(3, 4, f)
I assume you used a, b as the parameters in the template? A template works fine if you do not since it does not replace the fields with the parameters.
proc f(a, b:int):int = a + b
proc f(a:int):int = a
proc evalImpl(a, b:int, g:static[proc(a, b:int):int]):int =
let g = g
g(a, b)
template eval(a, b:int, g: untyped): untyped =
evalImpl(a, b, (proc(x, y:int):int)(g)) # Use x, y so it's not replaced by template
echo eval(10, 20, f)