There is a good reason to make IO schedulers pluggable: different media may need different scheduling. The canonical example is the flash vs. disk. It makes no sense to calculate optimal write order, or delay IO for flash.
In principle, I personally prefer one relatively well working piece of code over plenty of choice. There is also the argument that code can be written against a particular scheduling model. In a way, the situation is the opposite of what you said: the current unchangeable scheduler creates a stable API for *userland*, which is where the clients of scheduler are.
An example: When the 2.6 kernel arrived, it changed the way yield() operations on threads work, causing some applications to slow down drastically. Imagine if you had had choice of 3 different schedulers, and need to run app A which wants yield() behavior of one scheduler, and app B that wants the yield() of another. It could mean that you might not be able to use these two apps at the same time.