Below is the example I envisioned when Pontus revealed the Promise-based HTTP stuff. It will fetch all images referenced by a web page, nice and neat. The good thing about futures is that you’ll either get success or fail in the end, nothing in-between (if implemented correctly) (yeah, I know that you already like it, so I’m not really educating you.. :) )
Regarding “then” – maybe we can do it “The Pike Way” and add such a method too... It shouldn’t really conflict with the other stuff.
int main(int argc, array argv)
{
Standards.URI base_uri = Standards.URI (base_url);
Concurrent.Future img_futures =
Protocols.HTTP.Promise.get_url (base_url)
->flat_map (lambda (Protocols.HTTP.Promise.Success res)
// flat_map maps the result of the Future returned by
// get_url (.Success) to a new Future.
{
array(string) img_urls = ({});
Parser.HTML p = Parser.HTML();
p->add_tag ("img",
lambda (Parser.HTML p, mapping args)
{
if (string src = args["src"]) {
if (has_prefix (src, "http")) {
img_urls +=
({ Standards.URI (src, base_uri) });
}
}
});
p->finish (res->data)->read();
// img_futures will contain a Future for each URL in
// img_urls (since that's what
// Protocols.HTTP.Promise.get_url returns).
array(Concurrent.Future) img_futures =
map (img_urls, Protocols.HTTP.Promise.get_url);
// Concurrent.results wraps an array of Futures in a
// new Future. When all the wrapped Futures have
// succeeeded, the new future will succeed with an
// array of the wrapped values as its result.
return Concurrent.results (img_futures);
})
->map (lambda (array(Protocols.HTTP.Promise.Success) results)
// map simply maps the result of the Future to a plain
// value (no new Future.) We'll get an array of
// Protocols.HTTP.Promise.Success objects.
{
return results->data;
});
img_futures->on_success (lambda(array(string) img_data)
// img_data is an array of image data strings.
{
werror ("Got a bunch of data: %O\n",
map (img_data, sizeof));
});
img_futures->on_failure (lambda (mixed err)
{
werror ("Failed: %O\n", err);
});
return -1;
}