Skip to content

Commit 796156c

Browse files
authored
Improve custom iterator tutorial (#11901)
2 parents 0084c3f + 309b94c commit 796156c

1 file changed

Lines changed: 34 additions & 22 deletions

File tree

tutorials/scripting/gdscript/gdscript_advanced.rst

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -418,36 +418,37 @@ while() loops are the same everywhere:
418418
Custom iterators
419419
----------------
420420
You can create custom iterators in case the default ones don't quite meet your
421-
needs by overriding the Variant class's ``_iter_init``, ``_iter_next``, and ``_iter_get``
421+
needs by overriding ``_iter_init()``, ``_iter_next()``, and ``_iter_get()``
422422
functions in your script. An example implementation of a forward iterator follows:
423423

424424
::
425425

426426
class ForwardIterator:
427-
var start
428-
var current
429-
var end
430-
var increment
427+
var _start
428+
var _end
429+
var _increment
431430

432-
func _init(start, stop, increment):
433-
self.start = start
434-
self.current = start
435-
self.end = stop
436-
self.increment = increment
431+
func _init(start, end, increment):
432+
_start = start
433+
_end = end
434+
_increment = increment
437435

438-
func should_continue():
439-
return (current < end)
436+
func _should_continue(current):
437+
return current < _end
440438

441-
func _iter_init(arg):
442-
current = start
443-
return should_continue()
439+
func _iter_init(iter):
440+
# Initialize the state to store the current value.
441+
iter[0] = _start
442+
return _should_continue(iter[0])
444443

445-
func _iter_next(arg):
446-
current += increment
447-
return should_continue()
444+
func _iter_next(iter):
445+
iter[0] += _increment
446+
return _should_continue(iter[0])
448447

449-
func _iter_get(arg):
450-
return current
448+
func _iter_get(iter):
449+
# The state is not wrapped in an array for `_iter_get()`.
450+
# The iteration value is the same as the state.
451+
return iter
451452

452453
And it can be used like any other iterator:
453454

@@ -457,8 +458,19 @@ And it can be used like any other iterator:
457458
for i in itr:
458459
print(i) # Will print 0, 2, and 4.
459460

460-
Make sure to reset the state of the iterator in ``_iter_init``, otherwise nested
461-
for-loops that use custom iterators will not work as expected.
461+
It is possible but discouraged to store the state in a member variable.
462+
Multiple states are necessary in cases such as nested loops where the same
463+
iterator instance is used simultaneously. The ``iter`` parameter in
464+
``_iter_init()`` and ``_iter_next()`` is a single-element array so that updates
465+
can persist. Whereas in ``_iter_get()``, the state is is not wrapped because it
466+
is supposed to be read-only.
467+
468+
Returning ``true`` from ``_iter_init()`` and ``_iter_next()`` indicates that the
469+
iterator is valid. Returning ``false`` will terminate the loop.
470+
471+
For more details see :ref:`_iter_init() <class_Object_private_method__iter_init>`,
472+
:ref:`_iter_next() <class_Object_private_method__iter_next>`, and
473+
:ref:`_iter_get() <class_Object_private_method__iter_get>`.
462474

463475
Duck typing
464476
-----------

0 commit comments

Comments
 (0)