Topic was automatically imported from the old Question2Answer platform.
Asked By
abelgutierrez99
Hi,
I have a function that calculates the positions of all the tiles and stores them into a list, that is returned. However, I would like to use the tiles positions as long as they are generated, without the need of a big array.
Take this simple Python code:
def my_generator(n):
# initialize counter
value = 0
# loop until counter is less than n
while value < n:
# produce the current value of the counter
yield value
# increment the counter
value += 1
# iterate over the generator object produced by my_generator
for value in my_generator(3):
# print each value produced by generator
print(value)
As you can see, I can access to the values as they are calculated. I was wondering if there is something similar in GDScript 2.0. I found the await keyword, but I can’t access the variable of interest in the process, only the final value.
I know this post is old, but in case someone comes across this, GDScript’s coroutines are a stronger feature than C# generators and thus it’s possible to somewhat emulate generators using them.
E.g. you can create an abstract Generator class somewhat like this:
class Generator:
# func _impl(some_args...): IMPLEMENTED IN THE DERIVED CLASS
func _iter_init(arg):
_did_yield = false
self.callv("_impl", self._args)
_args = null
return _did_yield # if invocation of _impl() didn't finish by calling _yield(), assume it finished by returning
func _iter_next(arg):
if not _did_yield: return false # fail if we already had finished last time
_did_yield = false
_on_next_signal.emit() # _impl() is awaiting this signal - this way we resume it
return _did_yield
func _iter_get(arg): return _current_value
func _init(...args)->void:
self._args = args
var _args;
var _did_yield : bool = true;
var _current_value;
signal _on_next_signal();
func _yield(value)->Signal:
_current_value = value
_did_yield = true
return _on_next_signal; # return the signal that we want to await
and then write a generator straightforwardly by deriving from it, like this:
class SimpleRange
extends Generator
func _impl(start: int, end :int):
for i in range(start, end): await _yield(i)
Use it like you’d expect
for i in SimpleRange.new(1, 5): print(i) # prints "1234"
It’s a bit hacky and slow, but it works and I’ve had a few occasions where I was glad to be able to use this.