mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-06 20:04:18 +00:00
Merge pull request #4420 from yglukhov/closure-scope
Added closureScope template
This commit is contained in:
@@ -215,6 +215,12 @@ the closure and its enclosing scope (i.e. any modifications made to them are
|
||||
visible in both places). The closure environment may be allocated on the heap
|
||||
or on the stack if the compiler determines that this would be safe.
|
||||
|
||||
Creating closures in loops
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Since closures capture local variables by reference it is often not wanted
|
||||
behavior inside loop bodies. See `closureScope <system.html#closureScope>`_
|
||||
for details on how to change this behavior.
|
||||
|
||||
Anonymous Procs
|
||||
---------------
|
||||
@@ -223,7 +229,7 @@ Procs can also be treated as expressions, in which case it's allowed to omit
|
||||
the proc's name.
|
||||
|
||||
.. code-block:: nim
|
||||
var cities = @["Frankfurt", "Tokyo", "New York"]
|
||||
var cities = @["Frankfurt", "Tokyo", "New York", "Kyiv"]
|
||||
|
||||
cities.sort(proc (x,y: string): int =
|
||||
cmp(x.len, y.len))
|
||||
|
||||
@@ -3633,6 +3633,27 @@ proc `==` *(x, y: cstring): bool {.magic: "EqCString", noSideEffect,
|
||||
elif x.isNil or y.isNil: result = false
|
||||
else: result = strcmp(x, y) == 0
|
||||
|
||||
template closureScope*(body: untyped): stmt =
|
||||
## Useful when creating a closure in a loop to capture local loop variables by
|
||||
## their current iteration values. Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## var myClosure : proc()
|
||||
## # without closureScope:
|
||||
## for i in 0 .. 5:
|
||||
## let j = i
|
||||
## if j == 3:
|
||||
## myClosure = proc() = echo j
|
||||
## myClosure() # outputs 5. `j` is changed after closure creation
|
||||
## # with closureScope:
|
||||
## for i in 0 .. 5:
|
||||
## closureScope: # Everything in this scope is locked after closure creation
|
||||
## let j = i
|
||||
## if j == 3:
|
||||
## myClosure = proc() = echo j
|
||||
## myClosure() # outputs 3
|
||||
(proc() = body)()
|
||||
|
||||
{.pop.} #{.push warning[GcMem]: off, warning[Uninit]: off.}
|
||||
|
||||
when defined(nimconfig):
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
discard """
|
||||
output: ""
|
||||
"""
|
||||
import "../template/utemplates", "../closure/uclosures"
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
# This test is included from within tunittests
|
||||
import unittest
|
||||
|
||||
test "loop variables are captured by copy":
|
||||
test "loop variables are captured by ref":
|
||||
var funcs: seq[proc (): int {.closure.}] = @[]
|
||||
|
||||
for i in 0..10:
|
||||
let ii = i
|
||||
funcs.add do -> int: return ii * ii
|
||||
|
||||
check funcs[0]() == 100
|
||||
check funcs[3]() == 100
|
||||
|
||||
test "loop variables in closureScope are captured by copy":
|
||||
var funcs: seq[proc (): int {.closure.}] = @[]
|
||||
|
||||
for i in 0..10:
|
||||
closureScope:
|
||||
let ii = i
|
||||
funcs.add do -> int: return ii * ii
|
||||
|
||||
check funcs[0]() == 0
|
||||
check funcs[3]() == 9
|
||||
|
||||
|
||||
Reference in New Issue
Block a user