I've been making extensive use of continue functions (generators)
using a pattern whereby they will *yield* an awaitable (a
Concurrent.Future or a couple of other options), but will *return* a
final result (could be any type, eg int, string, mapping, array, etc).

This is working fairly nicely, with the exception that continue
functions have only one available return type annotation, which
therefore has to compass both types. This results in code like the
following:

Concurrent.Future get_user_info(int|string user, string|void type) {
    return /* a Concurrent.Future */;
}

array(string) token_for_user_login(string login) {
    return ({/* important stuff */});
}

continue Concurrent.Future|array(string) token_for_user_id_async(int userid) {
    string login = yield(get_user_info(userid))->login;
    return token_for_user_login(login);
}

Now, this means that the token_for_user_id_async function has, as far
as Pike is concerned, two equally possible return values - a Future or
an array. That causes issues further down the line. For example:

continue mapping|Concurrent.Future message_params(object channel,
mapping person, array param) {
    string token = yield((mixed)token_for_user_id_async(channel->userid))[0];
    // ...
}

My solution at the moment is to just cast things to mixed, effectively
forfeiting any kind of type checking, which is kinda fine, but I'm
wondering: might there be a better way?

It's somewhat tricky, because asynchronous functions in this way
depend on two quite different return types - one for a continue
return, the other for a final return. Does anyone else do this sort of
thing, and if so, how have you gone about it?

ChrisA

Reply via email to