Question: I'm playing with co-routines, and they're often described as useful for pipelines. I found a lecture from Berkeley that was very helpful ( <http://wla.berkeley.edu/~cs61a/fa11/lectures/streams.html#coroutines> ), but there's one thing I'm having trouble with. In that lecture, there's a diagram where a pipeline forks, then re-combines later. If order doesn't matter, recombining is easy, the consumer has one yield, but two producers are send()ing to it. But what if order matters? What if I want strict alternation (get a value from left fork, get a value from right fork, lather, rinse, repeat)? Is this possible?

Trivial recombine:

```
def producer1(ncr):
   while True:
       ncr.send(0)
def producer2(ncr):
   while True:
       ncr.send(1)
def combine():
    while True:
        s=(yield)
        print(s)
chain = combine()
chain.__next__()
producer1(chain)
producer2(chain)

```

I get an output of 0 1 0 1 etc, but I'm pretty sure that's a side effect of scheduling. Is there a way to guarantee the ordering, like a yield-from-1,yield-from-2?

To be clear, I know of `yield from` and `__await__`, but I haven't understood them yet.

Answer: 
This isn't difficult if you "pull" through your pipeline rather than "push":

```
def producer1():
    while True:
        yield 0

def producer2():
    while True:
        yield 1

def combine(*producers):
    while True:
        for producer in producers:
            val = next(producer)
            print(s)

combine(producer1(), producer2())

```

Should reliably produce alternating 1s and 0s

You can also have the final consumer (the thing that does work with each value- printing in this case) work as a receiver with no reference to the
producers if you really want:

```
def producer1():
    while True:
        yield 0

def producer2():
    while True:
        yield 1

def combine_to_push(co, *producers):
    while True:
        for producer in producers:
            s = next(producer)
            co.send(s)

def consumer():
    while True:
        val = (yield)
        print(val)

co = consumer()
co.__next__()
combine_to_push(co, producer1(), producer2())

```
I think figured out how to do it. It works with trivial pipelines, anyhow. Here's my combine:

```
class combiner():
    def __init__(self,n,ncr):
        self.q = [ deque() for i in range(n)]
        self.n = n
        self.x = 0
        self.ncr = ncr

    @coroutine
    def receiver(self,n):
        while True:
            s=(yield)
            self.q[n].append(s)
            self.sender()

    def sender(self):
        while True:
            if self.q[self.x]:
                self.ncr.send(self.q[self.x].popleft())
                self.x = (self.x + 1) % self.n
            else:
                break

```

this will round-robin between n streams. Basically, combiner.receiver() is a coroutine that takes data from a stream and puts it into a queue. There's a unique queue per stream. combiner.sender will flush out as much of the queue as it can manage then return.

I'm worrying a little that calling a function from a generator that then does a send might be *bad*, but I could just roll sender into receiver and that issue goes away....