> 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