KSH's coprocesses seem like expect, but inside the shell! Awesome.
O'Reilly's book "Learning the Korn Shell", §8.5 "Coroutines", goes over this a little bit.
Some examples of their use: (when looking at scripts, search for "read -p" and "print -p" to see the lines that interact with the coprocesses) (or, less commonly, "read -u" or "print -u")