On Mon, Jan 6, 2014 at 10:51 AM, Tobias Oberstein
<[email protected]> wrote:
> Am 06.01.2014 16:59, schrieb Guido van Rossum:
>> This API is more or less constrained (== copied from) the same API in
>> concurrent.futures and I don't think it is a big deal to have to work
>
> Sure, but why work around N times (at each and every place in user code) if
> it could be fixed in one place?

Why so many rhetorical questions?

>> around it. (The Tulip philosophy is roughly "if you find yourself
>> adding callbacks to futures, you're either writing a framework or
>
> So user code should be coroutine/sequential-style _only_? Mmh.

That's the Tulip way, yes.

>> doing it wrong" :-)
>
> In this example, I am not writing a framework, so I guess I must be doing it
> wrong;)
>
> Is this the preferred idiom for doing it right?

> def get_and_print_sales(product):
>    sales = yield from session.call("com.myapp.sales_by_product", product)
>    print("Sales {}: {}".format(product, sales))
>
> tasks = []
>
> for product in ["product2", "product3", "product5"]:
>    tasks.append(asyncio.Task(get_and_print_sales(product)))
> yield from asyncio.wait(tasks)

Yes, that looks good to me. You might use async() instead of Task().
And you could probably use a list comprehension to create the list of
tasks.

>> I usually prefer lambdas for this kind of adaptation, but in your
>> example (where the callback is added in a loop and one of the
>> parameters varies over the loop) you actually have to use
>> functools.partial() to avoid the late binding of that variable.
>
> The currying version would look like this:
>
> import functools
>
> def print_sales(product, future):
>    sales = future.result()
>    print("Sales {}: {}".format(product, sales))
>
> fl = []
>
> for product in ["product2", "product3", "product5"]:
>    f = session.call("com.myapp.sales_by_product", product)
>    f.add_done_callback(functools.partial(print_sales, product))
>    fl.append(f)
> yield from asyncio.gather(*fl)
>
> Quite verbose.

That's your hint that there's a better way. :-)

> FWIW, I don't understand why currying via functools.partial would be
> superior to adding args/kwargs forwarding to add_done_callback ..

Only because add_done_callback() is defined by PEP 3148 with the same signature.

> Both are "superior" to doing the obvious and dirty
>
> future.args = [product]
>
> though, since that doesnt't cut it for multiple callbacks with different
> args being added to the future.

Yeah, that might even stop working if I decided to add __slots__ to
the Future class.

-- 
--Guido van Rossum (python.org/~guido)

Reply via email to