capture macro now accepts variables of different types (#13356)
* Capture macro can now accept variables of different types * Add test * Update examples * Use let instead of var
This commit is contained in:
parent
5bf571f061
commit
f3eb0a5970
2 changed files with 16 additions and 6 deletions
|
|
@ -165,7 +165,7 @@ template distinctBase*(T: typedesc): typedesc {.deprecated: "use distinctBase fr
|
||||||
## reverses ``type T = distinct A``; works recursively.
|
## reverses ``type T = distinct A``; works recursively.
|
||||||
typetraits.distinctBase(T)
|
typetraits.distinctBase(T)
|
||||||
|
|
||||||
macro capture*(locals: openArray[typed], body: untyped): untyped {.since: (1, 1).} =
|
macro capture*(locals: varargs[typed], body: untyped): untyped {.since: (1, 1).} =
|
||||||
## Useful when creating a closure in a loop to capture some local loop variables
|
## Useful when creating a closure in a loop to capture some local loop variables
|
||||||
## by their current iteration values. Example:
|
## by their current iteration values. Example:
|
||||||
##
|
##
|
||||||
|
|
@ -175,14 +175,16 @@ macro capture*(locals: openArray[typed], body: untyped): untyped {.since: (1, 1)
|
||||||
## for i in 5..7:
|
## for i in 5..7:
|
||||||
## for j in 7..9:
|
## for j in 7..9:
|
||||||
## if i * j == 42:
|
## if i * j == 42:
|
||||||
## capture [i, j]:
|
## capture i, j:
|
||||||
## myClosure = proc () = echo fmt"{i} * {j} = 42"
|
## myClosure = proc () = echo fmt"{i} * {j} = 42"
|
||||||
## myClosure() # output: 6 * 7 == 42
|
## myClosure() # output: 6 * 7 == 42
|
||||||
## let m = @[proc (s: string): string = "to " & s, proc (s: string): string = "not to " & s]
|
## let m = @[proc (s: string): string = "to " & s, proc (s: string): string = "not to " & s]
|
||||||
## var l = m.mapIt(capture([it], proc (s: string): string = it(s)))
|
## var l = m.mapIt(capture(it, proc (s: string): string = it(s)))
|
||||||
## let r = l.mapIt(it("be"))
|
## let r = l.mapIt(it("be"))
|
||||||
## echo r[0] & ", or " & r[1] # output: to be, or not to be
|
## echo r[0] & ", or " & r[1] # output: to be, or not to be
|
||||||
var params = @[newIdentNode("auto")]
|
var params = @[newIdentNode("auto")]
|
||||||
|
let locals = if locals.len == 1 and locals[0].kind == nnkBracket: locals[0]
|
||||||
|
else: locals
|
||||||
for arg in locals:
|
for arg in locals:
|
||||||
params.add(newIdentDefs(ident(arg.strVal), freshIdentNodes getTypeInst arg))
|
params.add(newIdentDefs(ident(arg.strVal), freshIdentNodes getTypeInst arg))
|
||||||
result = newNimNode(nnkCall)
|
result = newNimNode(nnkCall)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ discard """
|
||||||
output: '''
|
output: '''
|
||||||
to be, or not to be
|
to be, or not to be
|
||||||
(v: 1)
|
(v: 1)
|
||||||
|
(w: -1)
|
||||||
(v: 1)
|
(v: 1)
|
||||||
|
(w: -1)
|
||||||
'''
|
'''
|
||||||
joinable: false
|
joinable: false
|
||||||
"""
|
"""
|
||||||
|
|
@ -14,13 +16,19 @@ var l = m.mapIt(capture([it], proc (s: string): string = it(s)))
|
||||||
let r = l.mapIt(it("be"))
|
let r = l.mapIt(it("be"))
|
||||||
echo r[0] & ", or " & r[1]
|
echo r[0] & ", or " & r[1]
|
||||||
|
|
||||||
type O = object
|
type
|
||||||
|
O = object
|
||||||
v: int
|
v: int
|
||||||
|
U = object
|
||||||
|
w: int
|
||||||
var o = O(v: 1)
|
var o = O(v: 1)
|
||||||
|
var u = U(w: -1)
|
||||||
var execute: proc()
|
var execute: proc()
|
||||||
capture [o]:
|
capture o, u:
|
||||||
execute = proc() =
|
execute = proc() =
|
||||||
echo o
|
echo o
|
||||||
|
echo u
|
||||||
execute()
|
execute()
|
||||||
o.v = -1
|
o.v = -1
|
||||||
|
u.w = 1
|
||||||
execute()
|
execute()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue