On 24 February 2015 at 21:00, Steven D'Aprano <steve@pearwood.info> wrote:
If I have a function which expects a *primed* coroutine, and you provide
an unprimed one, we get an obvious error:

py> def handle_primed(co):
...     for i in (1, 3, 5):
...             y = co.send(i)
...     return y
...
py> handle_primed(runningsum())  # Oops, unprimed!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in handle_primed
TypeError: can't send non-None value to a just-started generator

​Why would you ever want to use that function "unprimed", though? Writing "next(rs)" or "rs.send(None)" just seems like busywork​ to me; it's not something I'd write if I were writing pseudocode, so it's something I wish python didn't force me to write in order to use that language feature...

​But... you could just use a decorator to make that go away, I think? As in having a decorator along the lines of:

  def primed_coroutine(f):
      @wraps(f)
      def fprime(*args, **kwargs):
          co = f(*args, **kwargs)
          next(co)
          return co
      return fprime

so that you could write and use a coroutine just by having:

  @primed_coroutine
  def runningsum():
      total = 0
      while True:
          total += (yield total)​

​  handle_primed(runningsum())

​At least, now that I've thought of it, that's how I plan to write any generator-based coroutines in future...

Cheers,
aj​