def pipe(self, target):
        """
        Pipes this Recver to *target*. *target* can either be `Sender`_ (or
        `Pair`_) or a callable.

        If *target* is a Sender, the two pairs are rewired so that sending on
        this Recver's Sender will now be directed to the target's Recver::

            sender1, recver1 = h.pipe()
            sender2, recver2 = h.pipe()

            recver1.pipe(sender2)

            h.spawn(sender1.send, 'foo')
            recver2.recv() # returns 'foo'

        If *target* is a callable, a new `Pipe`_ will be created.  This Recver
        and the new Pipe's Sender are passed to the target callable to act as
        upstream and downstream. The callable can then do any processing
        desired including filtering, mapping and duplicating packets::

            sender, recver = h.pipe()

            def pipeline(upstream, downstream):
                for i in upstream:
                    if i % 2:
                        downstream.send(i*2)

            recver = recver.pipe(pipeline)

            @h.spawn
            def _():
                for i in xrange(10):
                    sender.send(i)

            recver.recv() # returns 2 (0 is filtered, so 1*2)
            recver.recv() # returns 6 (2 is filtered, so 3*2)
        """
        if callable(target):
            sender, recver = self.hub.pipe()

            # link the two ends in the closure with a strong reference to
            # prevent them from being garbage collected if this piped section
            # is used in a chain
            self.downstream = sender
            sender.upstream = self

            @self.hub.spawn
            def _():
                try:
                    target(self, sender)
                except vanilla.exception.Halt:
                    sender.close()

            return recver

        else:
            return target.connect(self)