mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 14:00:35 +00:00
introduce capture macro (#12712)
capture works for more cases than `closureScope`.
This commit is contained in:
@@ -42,6 +42,9 @@
|
||||
`sorted` does.
|
||||
- Added `sugar.collect` that does comprehension for seq/set/table collections.
|
||||
|
||||
- Added `sugar.capture` for capturing some local loop variables when creating a closure.
|
||||
This is an enhanced version of `closureScope`.
|
||||
|
||||
## Library changes
|
||||
|
||||
- `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations`
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
## This module implements nice syntactic sugar based on Nim's
|
||||
## macro system.
|
||||
|
||||
include system/inclrtl
|
||||
|
||||
import macros
|
||||
|
||||
proc createProcType(p, b: NimNode): NimNode {.compileTime.} =
|
||||
@@ -180,6 +182,30 @@ macro distinctBase*(T: typedesc): untyped =
|
||||
typeSym = getTypeImpl(typeSym)[0]
|
||||
typeSym.freshIdentNodes
|
||||
|
||||
macro capture*(locals: openArray[typed], body: untyped): untyped {.since: (1, 1).} =
|
||||
## Useful when creating a closure in a loop to capture some local loop variables
|
||||
## by their current iteration values. Example:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## import strformat, sequtils, sugar
|
||||
## var myClosure : proc()
|
||||
## for i in 5..7:
|
||||
## for j in 7..9:
|
||||
## if i * j == 42:
|
||||
## capture [i, j]:
|
||||
## myClosure = proc () = echo fmt"{i} * {j} = 42"
|
||||
## myClosure() # output: 6 * 7 == 42
|
||||
## 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)))
|
||||
## let r = l.mapIt(it("be"))
|
||||
## echo r[0] & ", or " & r[1] # output: to be, or not to be
|
||||
var params = @[newIdentNode("auto")]
|
||||
for arg in locals:
|
||||
params.add(newIdentDefs(ident(arg.strVal), freshIdentNodes getTypeImpl arg))
|
||||
result = newNimNode(nnkCall)
|
||||
result.add(newProc(newEmptyNode(), params, body, nnkProcDef))
|
||||
for arg in locals: result.add(arg)
|
||||
|
||||
when (NimMajor, NimMinor) >= (1, 1):
|
||||
macro outplace*[T](arg: T, call: untyped; inplaceArgPosition: static[int] = 1): T =
|
||||
## Turns an `in-place`:idx: algorithm into one that works on
|
||||
|
||||
12
tests/closure/tcapture.nim
Normal file
12
tests/closure/tcapture.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
discard """
|
||||
output: '''
|
||||
to be, or not to be'''
|
||||
joinable: false
|
||||
"""
|
||||
|
||||
import sequtils, sugar
|
||||
|
||||
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)))
|
||||
let r = l.mapIt(it("be"))
|
||||
echo r[0] & ", or " & r[1]
|
||||
Reference in New Issue
Block a user