> Pike now (8.1) has a decent promise/future subsystem. It's always had
> great handling of multiple asynchronous operations (GUI, socket, time
> delay, etc) with the convenience of just returning -1 from main.
> Interested in people's opinions on whether it would be of value to
> introduce generators and (built on them) asynchronous functions.
>
> I'm borrowing terminology heavily from Python and ECMAScript here, and
> both of them have drawn from prior art.
>
> A *generator function* is a function that can be partially run, then
> set aside until resumed. Effectively, its stack frame can be
> encapsulated in an object for future use. It would look something like
> this:
>
> int get_numbers() {
>     write("Starting\n");
>     yield 1;
>     write("Continuing\n");
>     yield 2;
>     write("Finishing\n");
>     return 3;
> }
>
> Calling get_numbers would prepare an execution context, but not
> actually begin running the function at all. The caller would get back
> a *generator object*. Asking this generator object to produce its next
> value would begin executing the function, triggering the call to
> write, and would stop at the first yield point, returning that value
> (1). Asking for another value resumes the function, triggering the
> second write, and returns the next yielded value. The third time you
> request a value, it would run the function to completion, and report
> that it returned (not yielded) 3.
>
> (The types yielded don't have to match the type of the return value.
> I'm not sure if there's a good way to declare the yielded types, or if
> it's best to just assume 'mixed'.)

Not matching the declared type seems like a bad idea.

> A generator object would be an Iterator, allowing you to loop over the
> yielded values easily:

This is a separate issue. Note that iterators have both indices and values.

> foreach (get_numbers() ;; int num)
>
> The 'yield' keyword would be an expression/operator, allowing you to
> send a value back into the generator function as the result of the
> yield expression.

This seems to be something entirely different??

Anyway, I have a proof of concept implementation of the first use:

--- generator_test.pike ---

continue int foo(int start, int end)
{
  while (start <= end)
    continue return start++;
}

int main(int argc, array(string) argv)
{
  function(:int) bar = foo(4, 8);

  int i;
  do {
    i = bar();
    if (zero_type(i)) break;
    werror("%d\n", i);
  } while (1);
}

---------------------------

$ ./pike generator_test.pike 
4
5
6
7
8
0

Note that the ending 0 is due to the implicit return 0 at the end of
Pike functions.

        /grubba

Reply via email to