The previous code was checking the threads in the order they were
created. So the progress update would be blocked on an earlier thread
even if later thread were already done.
Add to that that multiple instances of `cargo build` cannot run in
parallel, they will be serialized instead. So if the exercises needs to
be recompiled, depending on the order those `cargo build` are run,
the first update can be a long time coming.
So instead of relying on the thread terminating, use a channel to get
notified when an exercise check is done, regardless of the order they
finish in.
This allows for skipping repeating "next" when multiple exercises
are done at once, or when earlier exercises have been updated/changed
(and thus must be redone) while still working of the whole set (i.e.
the final check_all is not yet available to flag those undone exercises)
The previous code run the check on all exercises but only updates one
exercise (the first that failed) even if multiple failed. The user won't
be able to see all the failed exercises when viewing the list, and will
have to run check_all after each fixed exercise.
This change will update all the exercises so the user can see all that
failed, fix them all, and only then need run check_all again.
Some people would get stuck on this exercise, trying to understand the meaning
behind foo, fuzz, baz etc. Making the theme of the code make a little more sense
to humans should hopefully prevent people from getting confused by abstract and
non-sensical tests.