rungen icon indicating copy to clipboard operation
rungen copied to clipboard

generic generator runtimes

Open joshrtay opened this issue 9 years ago • 4 comments

Just created something really similar called koax. Would love to get your thoughts.

joshrtay avatar Feb 04 '16 19:02 joshrtay

Hi,

I like some of the ideas in koax :

Using the term middleware instead of 'control' is good, people (from redux and express/koa world) can easily understand its usecase and the fact that is a concept that allow to extend the runtime.

In my implementation, I've used simple functions to define 'middlewares' with some callbacks, but having multiple callbacks can be difficult to get for users (the differences between each callback). Using generators like you did can be a good alternative. While I've not a fixed idea about this yet, maybe we could try this to have the simplest API possible.

I'm not sure but in your implementation, I think there might be some limitations, because of the fact that you traverse middleware in a linear way and dont loop over them in each yield.

say you have a middleware handling a generator that returns a promise, and another one handling promises that returns generators, it's kind of hard to reuse the generator middleware in the promise middleware to get the "leaf" value. (I dont know if this is clear enough).

I also find the "functor" concept a little bit confusing.

I have some questions about handling errors in the KOAX.

youknowriad avatar Feb 04 '16 20:02 youknowriad

So i'm not sure I completely understand your question about the middleware implementation. But let me see if I can clarify.

That's essentially correct - the middleware is traversed in a linear fashion, ending the traverse when a middleware returns a value other than next. However, Koax actually does loop over the entire middleware stack with each yield. yield starts a new traverse of the middleware stack with the value provided used as the action in the traverse and the return value of the traverse "yielded". In fact, the following two examples are equivalent:

let app = koax()

app.use(function * (action, next) {
  if (action === 'qux') return yield 'foo'
  else return 'woot'
})
let app = koax()

app.use(function * (action, next) {
  if (action === 'qux') return yield app('foo')
  else return 'woot'
})

It's also important to note that at the top of the middleware stack there is implicit middleware that handles promises, arrays, generators, and functions.

Functors are best not to worry about. Basically it's a way of customizing how data types should be resolved and yielded. You can add a map function to any value that is dispatched to customize how it will be processed. Arrays for example, inherently map over each value in the array, so when an array is yielded every value is dispatched to the middleware stack before being resolved. This leads to the behavior you would expect.

Let me know when you've formulated your questions about errors. I haven't really thought about them too much yet. Shouldn't be too different from the way the co handles them.

joshrtay avatar Feb 04 '16 22:02 joshrtay

It might be easies to just look at the code. @koax/compose handles the traversing and @koax/bind adds the middleware layer that handles the promises, arrays, and generators as well as sets up the recursive yields.

joshrtay avatar Feb 05 '16 00:02 joshrtay

I see, so that answers my question about traversing middlewares. I'm curious to see how these things will evolve and how folks would get to deal with them.

youknowriad avatar Feb 05 '16 08:02 youknowriad