To break this down into multiple steps `varargs[T, conversionProc]` allows you
to take in comma separated values or arrays, but since arrays have to be
homogeneous you cannot do `query = {}` or `query = []`.
proc toStrTup[T, Y](a: (T, Y)): (string, string) = ($a[0], $a[1])
proc doThing(args: varargs[(string, string), toStrTup]) = echo args
doThing (10, 20), ("hmm", 40), ("huh", (10, 20, 30))
Run
If that suffices it's done and we can all go home.
If that does not suffice we need to bring in macros to solve this problem.
Something along the lines of
import std/[macros, strformat]
macro toQuery*(arr: untyped, querySize: static range[2..int.high]): untyped
=
result = nnkBracket.newNimNode()
case arr.kind
of nnkBracket:
for ele in arr:
if ele.kind in {nnkTupleConstr, nnkPar}:
if ele.len != querySize:
error(fmt"Expected a tuple airty of '{querySize}', but got a size
of '{ele.len}'", ele)
result.add nnkTupleConstr.newNimNode()
for field in ele:
result[^1].add newCall("$", field)
of nnkTableConstr:
if querySize != 2:
error(fmt"Expected a tuple of '{querySize}' airty, but got a table.",
arr)
for tupleConstr in arr:
result.add nnkTupleConstr.newNimNode
result[^1].add newCall("$", tupleConstr[0])
result[^1].add newCall("$", tupleConstr[1])
else:
error(fmt"Expected '{{a: b}}' or '[(a, b)]', but got '{arr.repr}'.",
arr)
echo result.repr
template toQuery*(arr: untyped): untyped = toQuery(arr, 2)
proc doThing(args: varargs[(string, string)]) = echo args
let a = @[10, 20, 30, 40]
doThing toQuery {10: 20, "hmm": "huh", (10, 20, 30): a}
doThing toQuery [(10, 20), ("hmm", "huh"), ((10, 20, 30), a)]
assert toQuery([(10, 20), ("hmm", "huh"), ((10, 20, 30), a)]) ==
toQuery({10: 20, "hmm": "huh", (10, 20, 30): a})
Run
Notice that due to how semantic analysis works you cannot do `{...}.toQuery` or
`[...].toQuery`.