Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement return value from yield() #1397

Closed
bil-bas opened this issue Feb 19, 2015 · 3 comments
Closed

Implement return value from yield() #1397

bil-bas opened this issue Feb 19, 2015 · 3 comments

Comments

@bil-bas
Copy link
Contributor

bil-bas commented Feb 19, 2015

To create generator functions, we need yield(value) to be implemented. This would act like yield(), but 'value' would be passed back and returned from the resume() call.

This would allow range() to be made into an iterator, rather than creating a potentially huge array.

This would also be a step towards nice features like list/dict comprehension.

@jamie-pate
Copy link
Contributor

jamie-pate commented May 29, 2018

Unpleasant workaround:

func xrange(count, dict):
	var i = 0
	while i < count:
 		dict.next = i
		yield()
		i += 1

func do_stuff():
	var curr = {}
	var it = xrange(5, curr)
	while curr.value != null:
		print(curr.value)
		it.resume()

@busy8
Copy link

busy8 commented Jun 4, 2019

I've just started working with Godot (liking it so far) but I agree that it feels that yield() should be able to return more than the function state. Yield is like returning with the ability to resume() so the function should be able to "return" a value by yielding.

One possible approach I have been thinking of is augmenting [GDScript]FunctionState
( https://docs.godotengine.org/en/3.1/classes/class_gdscriptfunctionstate.html )
to have a method value() which returns the argument to yield().

func co1():
     yield(5)

s = co1()
print(s.value())   # prints 5

GDscript already has a yield which takes two values and waits on a signal. However, this one argument version would just return its argument in the FunctionState. With just that change a generator could be written like:

func xrange(count):
	var i = 0
	while i < count:
		yield(i)

func do_stuff():
	var it = xrange(5)
	while it:
		print(it.result())
		it = it.resume()

This works quite nicely but there is a subtlety worth considering. When the coroutine function returns (instead of yielding) a value is returned not a FunctionState. In the above example null is returned (because the function is void) which we test to stop the loop in do_stuff(). If the coroutine function returns a value [eg. imagine return false at the end of xrange()] then that test would break.

I think I'll take a look at the code.
IMO, yield(value) would be, erm, valuable.

EDIT: Looking at the code there are complications with the signal version of yield so the section that I'd written below about it is removed for now. May elaborate later.

@vnen
Copy link
Member

vnen commented May 25, 2020

There's some problems on how yield works, so it'll replaced by await which is more straight-forward. I'm not sure yet whether we'll do actual generators.

If you are still interested in the idea of adding generators, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). You can reference this issue and summarize the ideas in the proposal. Thanks in advance!

@vnen vnen closed this as completed May 25, 2020
@vnen vnen added the archived label May 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants