Generators in Lone Lisp (matheusmoreira.com)

by matheusmoreira 11 comments 63 points
Read article View on HN

11 comments

[−] hencq 50d ago
I like the overview given in this Stackoverflow answer [1] (based on an even earlier comment) which classifies different types of continuations:

- Asymmetric or symmetric

- Stackful or stackless

- Delimited or undelimited

- Multi-prompt or single prompt

- Reentrant or non-reentrant

- Clonable or not

Based on that these generators (or semi-coroutines as the article also calls them) seem to be asymmetric, stackful, delimited, single prompt(?), non-reentrant continuations.

[1] - https://stackoverflow.com/questions/62817878/what-are-the-sp...

[−] matheusmoreira 50d 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.

[−] hencq 50d ago
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.

[−] matheusmoreira 50d ago
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.

[−] bjoli 50d ago
Fun read! If anyone is interested in more, I believe Andy Wingo has written about the implementation of delimited continuations in guile scheme over at https://wingolog.org
[−] geon 50d ago
This is awesome!

I haven't seen Lone Lisp before. Is it meant to be like a Symbolics Lisp Machine, where the entire userspace is lisp?

I really like using generators in typescript. They make a lot of problems much easier.