mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-25 12:25:08 +00:00
Clarify the sense in which Nim supports recursive iterators in the (#15834)
manual, the tutorial, and the `tbintree` test.
This commit is contained in:
@@ -4031,10 +4031,13 @@ Closure iterators and inline iterators have some restrictions:
|
||||
1. For now, a closure iterator cannot be executed at compile time.
|
||||
2. ``return`` is allowed in a closure iterator but not in an inline iterator
|
||||
(but rarely useful) and ends the iteration.
|
||||
3. Neither inline nor closure iterators can be recursive.
|
||||
3. Neither inline nor closure iterators can be (directly)* recursive.
|
||||
4. Neither inline nor closure iterators have the special ``result`` variable.
|
||||
5. Closure iterators are not supported by the js backend.
|
||||
|
||||
(*) Closure iterators can be co-recursive with a factory proc which results
|
||||
in similar syntax to a recursive iterator. More details follow.
|
||||
|
||||
Iterators that are neither marked ``{.closure.}`` nor ``{.inline.}`` explicitly
|
||||
default to being inline, but this may change in future versions of the
|
||||
implementation.
|
||||
@@ -4129,7 +4132,41 @@ parameters of an outer factory proc:
|
||||
for f in foo():
|
||||
echo f
|
||||
|
||||
The call can be made more like an inline iterator with a for loop macro:
|
||||
|
||||
.. code-block:: nim
|
||||
import macros
|
||||
macro toItr(x: ForLoopStmt): untyped =
|
||||
let expr = x[0]
|
||||
let call = x[1][1] # Get foo out of toItr(foo)
|
||||
let body = x[2]
|
||||
result = quote do:
|
||||
block:
|
||||
let itr = `call`
|
||||
for `expr` in itr():
|
||||
`body`
|
||||
|
||||
for f in toItr(mycount(1, 4)): # using early `proc mycount`
|
||||
echo f
|
||||
|
||||
Because of full backend function call aparatus involvment, closure iterator
|
||||
invocation is typically higher cost than inline iterators. Adornment by
|
||||
a macro wrapper at the call site like this is a possibly useful reminder.
|
||||
|
||||
The factory ``proc``, as an ordinary procedure, can be recursive. The
|
||||
above macro allows such recursion to look much like a recursive iterator
|
||||
would. For example:
|
||||
|
||||
.. code-block:: nim
|
||||
proc recCountDown(n: int): iterator(): int =
|
||||
result = iterator(): int =
|
||||
if n > 0:
|
||||
yield n
|
||||
for e in toItr(recCountDown(n - 1)):
|
||||
yield e
|
||||
|
||||
for i in toItr(recCountDown(6)): # Emits: 6 5 4 3 2 1
|
||||
echo i
|
||||
|
||||
Converters
|
||||
==========
|
||||
@@ -4619,8 +4656,8 @@ The following example shows a generic binary tree can be modeled:
|
||||
|
||||
iterator preorder*[T](root: BinaryTree[T]): T =
|
||||
# Preorder traversal of a binary tree.
|
||||
# Since recursive iterators are not yet implemented,
|
||||
# this uses an explicit stack (which is more efficient anyway):
|
||||
# This uses an explicit stack (which is more efficient than
|
||||
# a recursive iterator factory).
|
||||
var stack: seq[BinaryTree[T]] = @[root]
|
||||
while stack.len > 0:
|
||||
var n = stack.pop()
|
||||
|
||||
@@ -511,8 +511,8 @@ containers:
|
||||
|
||||
iterator preorder*[T](root: BinaryTree[T]): T =
|
||||
# Preorder traversal of a binary tree.
|
||||
# Since recursive iterators are not yet implemented,
|
||||
# this uses an explicit stack (which is more efficient anyway):
|
||||
# This uses an explicit stack (which is more efficient than
|
||||
# a recursive iterator factory).
|
||||
var stack: seq[BinaryTree[T]] = @[root]
|
||||
while stack.len > 0:
|
||||
var n = stack.pop()
|
||||
|
||||
@@ -55,8 +55,8 @@ proc find*[Ty2](b: PBinaryTree[Ty2], data: Ty2): bool =
|
||||
|
||||
iterator preorder*[T](root: PBinaryTree[T]): T =
|
||||
# Preorder traversal of a binary tree.
|
||||
# Since recursive iterators are not yet implemented,
|
||||
# this uses an explicit stack:
|
||||
# This uses an explicit stack (which is more efficient than
|
||||
# a recursive iterator factory).
|
||||
var stack: seq[PBinaryTree[T]] = @[root]
|
||||
while stack.len > 0:
|
||||
var n = stack.pop()
|
||||
|
||||
Reference in New Issue
Block a user