Change to new `yield` based API

Thanks to @jeromew for most of the initial work on this.