Hacker News new | past | comments | ask | show | jobs | submit login

Looking at the http://www.dabeaz.com/coroutines/Coroutines.pdf recommended in the article, coroutines remind me of partial functions in Python. Can folks who know more about Python than I do explain when to use coroutines vs partial functions? Is the difference only in the "generator" part of it?



A partial function in Python is just a wrapper around the underlying function, that automatically supplies whatever arguments you passed in to functools.partial. It doesn't change anything about how the function is executed.

A coroutine gets executed differently from an ordinary function (or an ordinary generator, for that matter); when you call it using the await syntax, the Python interpreter can choose to run some other code while it is waiting for your function to return a result from I/O (for example, a network request). A normal function call doesn't allow that. (A generator might, if you use yield from and do a number of other things, but you have to do them by hand, whereas the await syntax does it all for you automatically inside the interpreter.)


This is slightly misleading considering async funcions are just simply generators and nothing but parsing the keywords is actually implemented in the interpreter. The whole logic is in the asyncio library.

This is a great talk where the presenter goes into how asyncio works in detail and builds a mini version of the asyncio library:

https://youtu.be/M-UcUs7IMIM


> async funcions are just simply generators and nothing but parsing the keywords is actually implemented in the interpreter.

As I understand it, async functions have an extra flag that ordinary generators don't have, and the interpreter does some different things if that flag is present. But I have not dug deeply into the source code.


Are you familiar with the distinction between synchronous and asynchronous execution? Let's start there.


Oh sure. I was just discussing in the context of the example given in David Beazly's slides.

  def grep(pattern):
      print "Looking for %s" % pattern
      while True:
          line = (yield)
          if pattern in line:
              print line,
You initialize the coroutine with g = grep("python"). Isn't this step same as having a partial function with it's `pattern` argument with value "python"?

  def grep(pattern, line):
      if pattern in line:
          print line,
And then:

  g = partial(grep, pattern="python")
  g(line='python in a line')
I'm sure this is a very simple example of coroutines, but if this is all I want to do (setting aside async vs sync for a moment), why would I use a coroutine here instead of a partial function?

EDIT: As I see more examples of coroutines especially the pipelining use cases, I was wrong and agree that it's completely different from partial functions.


I think I see where the confusion is coming from. A coroutine can be nexted repeatedly. A partial function can only be called once. The coroutine in the example is just a toy, so it's effectively the same as calling a partial many times in a loop. A more interesting coroutine might encapsulate state that changes across next'ing. Yes, other kinds of functions can change state across calls, too... It turns out many techniques can accomplish the same thing.


Exactly what I thought. I also made an edit to refer to the process pipelining use cases which makes it more clear. Thanks!




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: