Interesting. Can you show an example of how Lua's interface to the underlying platform improves on Python? Doesn't replacing APIs with protocols merely shift the breakage to higher-level logical errors rather than lower-level mechanical ones?
Lua is under-coupled with the base system. For the longest time it wouldn't even support dynamically loaded modules because it wasn't portable. It wasn't part of C89.
So when one uses Lua, it is up to the user to supply IO. This threading through the needle or hour-glass allows the users (embedder) to define how the scripts interact with the base system. This makes them more resilient over time, the interactions are better specified and highly mediated.
Somewhat analogous to the library vs framework dichotomy. Libraries survive better than frameworks do.
Fascinating! Seems to have some commonality with dependency injection, which is one of my interests (https://github.com/akkartik/mu#readme)
Can you point me at any Lua docs where I can read more about overriding IO in Lua?
The surface area of POSIX is too high to build systems that can run for 10s or hundreds of years. Look at the design of Lua over Python. The assumptions it makes of the underlying platform are much much cleaner, thus it is more portable and easier to debug platform issues.