Solution (source code)

= Solution

Use the \b[<adapter pattern>], keeping the existing component <software object> in both directions:

``
class PipeAsChannel(pipe: Pipe) extends Channel {
  override def apply(n: Int): Int = {
    pipe.consume(n)
    pipe.result
  }
}

class ChannelAsPipe(channel: Channel, initialResult: Int) extends Pipe {
  private var last = initialResult
  override def consume(n: Int): Unit = {
    last = channel(n)
  }
  override def result: Int = last
}
``

The first adapter feeds the input before reading the pipe's output. The second invokes the channel exactly once per consume and caches its returned output; subsequent result queries do not advance it. \b[Its initial result must be supplied explicitly], because a general channel <object interface> exposes no initial-output query. Calling the channel on a dummy input during construction would mutate arbitrary state and would invent behavior the <object interface> does not promise.

These adapters preserve the sequential update/output behavior after each real input, assuming no interfering access to the wrapped component. They do not claim a perfect inverse for every aspect of the original <object interfaces>: pipe initialization is additional observable state, whereas a channel alone does not specify that observation.