Skip to content

yieldAll and recursive generators #7

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

Closed
ilya-g opened this issue Aug 29, 2016 · 4 comments
Closed

yieldAll and recursive generators #7

ilya-g opened this issue Aug 29, 2016 · 4 comments

Comments

@ilya-g
Copy link
Member

ilya-g commented Aug 29, 2016

Investigate whether it's possible to implement efficient tail-recursive generators with yieldAll suspension function and the nested iterators technique, described here: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/specsharp-iterators.pdf

fun fromTo(from: Int, to: Int) = generate {
    if (from > to) return
    yield(from)
    yieldAll(fromTo(from + 1, to))
}
@h0tk3y
Copy link
Contributor

h0tk3y commented Oct 24, 2016

I'm currently investigating this. As to the tail-recursive generators, seems like we can only achieve that using handleResult(), which requires a coroutine to return the tail sequence:

fun fromTo(from: Int, to: Int) = generateWithTail f@{
    if (from > to) return@f emptySequence()
    yield(from)
    return@f fromTo(from + 1, to)
}

As far as I understand, there's no other way to learn whether a nested iterator yield is the last suspension in the block and the continuation is actually a NOP that will immediately finish the coroutine block. I guess it would require some continuation metadata (though not much). Or is there already a way to learn that?

@elizarov
Copy link
Contributor

buildSequence is not a part of stdlib with both yield and yieldAll support provided out-of-the-box.

@ilya-g
Copy link
Member Author

ilya-g commented Jan 19, 2017

Note that the mentioned nested iterator optimization is not implemented.

@elizarov
Copy link
Contributor

elizarov commented Jan 19, 2017

It actually is conceptually available with suspending functions in even nicer way:

suspend tailrec fun SequenceBuilder<Int>.fromTo(from: Int, to: Int) {
    if (from > to) return
    yield(from)
    fromTo(from + 1, to)
}

then do buildSequence { fromTo(1, 1000) } (crashed backend right now, though)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants