what would be the idiomatic way to write this D code in nim?
it calls a function by name (provided at runtime), trying all possibilities until a match is found.
import std.stdio:writeln;
void fun1(){writeln("ok1");}
void fun2(){writeln("ok2");}
void callFun(string fun){
static foreach(funi; ["fun1", "fun2"]){
if(funi == fun){
mixin(funi~"();");
return;
}
}
assert(0);
}
void main(){
callFun("fun1");
}
EDIT: this works (sort of, needs more care to handle function name not foud), but is there a better way?
import strformat
macro callFun(fun: string): typed =
result = newNimNode(nnkStmtList)
for target in ["fun1", "fun2"]:
result.add(parseStmt(fmt"""if "{target}" == fun: {target}()"""))
maybe related to https://forum.nim-lang.org/t/3038 but didn't find my answer there (registering procs at compile-time)
Here are 2 ways
## Sol 1 - if you can get by with identifier input
proc fun1() = echo "ok1"
proc fun2() = echo "ok2"
template callfun(fun: untyped) =
fun()
## Sol 2 - if you really need string input
## This also unrolls the loop
import macros
const fns = [fun1, fun2]
macro callfun2(fun: string, listfunc: typed): untyped =
result = newStmtList()
echo listfunc.symbol.getImpl.treerepr
for function in listfunc.symbol.getImpl:
let f_str = $function
result.add quote do:
if `f_str` == `fun`:
`function`()
when isMainModule:
callfun(fun1)
callfun2("fun2", fns)
@timothee, use procvar annotation if you have the proc defined
proc echoa() {.procvar.} =
echo "proca"
proc echob() {.procvar.} =
echo "procb"
let echos = @[echoa, echob]
for f in echos:
f()
You can use together with enum as matching case or any other method, like using index of array or string key table etc