Modify Accessors

Since that control flow is so problematic, could we just get rid of the need to bother with it? Say you have this generator:

func generate() {
   yield a
   yield b
   yield c
}

and the first yield fails, we could just continue running the function as if nothing happened. The following yields would just become no-ops. As far as the generator is concerned, yield can't fail, it'll just do nothing if the yielding context disappears.

We should also have a way for the generator to avoid doing useless work, but as an optimisation. Just check for the context being broken:

func generate() {
   yield &a
   if brokenYield { return }
   yield &b
   if brokenYield { return }
   yield &c
}

So if you don't bother handling the error path, your generator will continue to behave correctly. The only downside is it'll do more work than necessary.

There's also no need to check after every yield: only check when it actually avoids work:

func generate() {
   var (a, b) = fetchAB()
   yield &a
   yield &b
   commitAB(a, b)

   if brokenYield { return } // this is a good point to stop

   var (c, d) = fetchCD()
   yield &c
   yield &d
   commitCD(c, d)
}