← Back to context

Comment by matheusmoreira

15 hours ago

That's a great overview. Yeah they are asymmetric, Wikipedia says symmetric and asymmetric correspond to coroutines and semicoroutines. They are also stackful and delimited. They are single shot by design, though I could easily make it possible to restart the generator from scratch if needed.

As for single prompt vs multiprompt... I'm not too sure about this one. I have a check to prevent recursion but nesting generators shouldn't be a problem since they keep track of their own callers.

I think lone's generators have composability issues due to the stack separation. For example, calling a generator g2 inside another generator g1 doesn't transparently yield values from g2 to g1's caller. I've been wondering about how to fix this without a Python-like yield from primitive.

Very cool stuff and great written article. Lone looks very interesting!

Are you planning to use your design to support things like exceptions as well? I think that's where that multi-prompt ability becomes important (yielding from a nested coroutine). Racket has prompts and aborts, which is essentially a 'yield to' primitive.

  • Thank you. Proper exception/condition handling is a high priority item on my list. It's something that is long overdue... Lone currently hard exits on literally any error.

    My delimited continuations article also talks about exception handling:

    https://www.matheusmoreira.com/articles/delimited-continuati...

    Throw/catch are just delimited continuations which don't actually capture the continuation. The machinery is already in place. If I copied the control/transfer primitives and removed the continuation code, I'd have a functional exceptions handling mechanism.

    In suppose I can use tagged prompts to catch some exceptions and not others. Place a symbol in the stack delimiter, then the transfer primitive can look for it and skip anything that doesn't match. Untagged prompts just use nil as the tag.