document macros.unpackVarargs (#18106)
* deprecate macros.unpackVarargs * un-deprecate unpackVarargs and add docs+runnableExamples * update examples + tests with varargs[typed]
This commit is contained in:
parent
98ea61f09b
commit
18b4774311
3 changed files with 66 additions and 0 deletions
|
|
@ -1682,6 +1682,21 @@ macro getCustomPragmaVal*(n: typed, cp: typed): untyped =
|
|||
error(n.repr & " doesn't have a pragma named " & cp.repr, n)
|
||||
|
||||
macro unpackVarargs*(callee: untyped; args: varargs[untyped]): untyped =
|
||||
## Calls `callee` with `args` unpacked as individual arguments.
|
||||
## This is useful in 2 cases:
|
||||
## * when forwarding `varargs[T]` for some typed `T`
|
||||
## * when forwarding `varargs[untyped]` when `args` can potentially be empty,
|
||||
## due to a compiler limitation
|
||||
runnableExamples:
|
||||
template call1(fun: typed; args: varargs[untyped]): untyped =
|
||||
unpackVarargs(fun, args)
|
||||
# when varargsLen(args) > 0: fun(args) else: fun() # this would also work
|
||||
template call2(fun: typed; args: varargs[typed]): untyped =
|
||||
unpackVarargs(fun, args)
|
||||
proc fn1(a = 0, b = 1) = discard (a, b)
|
||||
call1(fn1, 10, 11)
|
||||
call1(fn1) # `args` is empty in this case
|
||||
if false: call2(echo, 10, 11) # would print 1011
|
||||
result = newCall(callee)
|
||||
for i in 0 ..< args.len:
|
||||
result.add args[i]
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ template `.=`*[T](s: SharedPtr[T]; field, value: untyped) =
|
|||
from macros import unpackVarargs
|
||||
|
||||
template `.()`*[T](s: SharedPtr[T]; field: untyped, args: varargs[untyped]): untyped =
|
||||
# xxx this isn't used, the test should be improved
|
||||
unpackVarargs(s.x.field, args)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,3 +10,53 @@ block: # hasArgOfName
|
|||
|
||||
block: # bug #17454
|
||||
proc f(v: NimNode): string {.raises: [].} = $v
|
||||
|
||||
block: # unpackVarargs
|
||||
block:
|
||||
proc bar1(a: varargs[int]): string =
|
||||
for ai in a: result.add " " & $ai
|
||||
proc bar2(a: varargs[int]) =
|
||||
let s1 = bar1(a)
|
||||
let s2 = unpackVarargs(bar1, a) # `unpackVarargs` makes no difference here
|
||||
doAssert s1 == s2
|
||||
bar2(1, 2, 3)
|
||||
bar2(1)
|
||||
bar2()
|
||||
|
||||
block:
|
||||
template call1(fun: typed; args: varargs[untyped]): untyped =
|
||||
unpackVarargs(fun, args)
|
||||
template call2(fun: typed; args: varargs[untyped]): untyped =
|
||||
# fun(args) # works except for last case with empty `args`, pending bug #9996
|
||||
when varargsLen(args) > 0: fun(args)
|
||||
else: fun()
|
||||
|
||||
proc fn1(a = 0, b = 1) = discard (a, b)
|
||||
|
||||
call1(fn1)
|
||||
call1(fn1, 10)
|
||||
call1(fn1, 10, 11)
|
||||
|
||||
call2(fn1)
|
||||
call2(fn1, 10)
|
||||
call2(fn1, 10, 11)
|
||||
|
||||
block:
|
||||
template call1(fun: typed; args: varargs[typed]): untyped =
|
||||
unpackVarargs(fun, args)
|
||||
template call2(fun: typed; args: varargs[typed]): untyped =
|
||||
# xxx this would give a confusing error message:
|
||||
# required type for a: varargs[typed] [varargs] but expression '[10]' is of type: varargs[typed] [varargs]
|
||||
when varargsLen(args) > 0: fun(args)
|
||||
else: fun()
|
||||
macro toString(a: varargs[typed, `$`]): string =
|
||||
var msg = genSym(nskVar, "msg")
|
||||
result = newStmtList()
|
||||
result.add quote do:
|
||||
var `msg` = ""
|
||||
for ai in a:
|
||||
result.add quote do: `msg`.add $`ai`
|
||||
result.add quote do: `msg`
|
||||
doAssert call1(toString) == ""
|
||||
doAssert call1(toString, 10) == "10"
|
||||
doAssert call1(toString, 10, 11) == "1011"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue