| But that doesn't tell you _why_ that choice is a good idea! My favourite explanation comes from property based testing. In general, you have the following property: For any lists xs and ys, all(xs) and all(ys) == all(xs + ys)
If you want to keep that property as simple as possible, you have to define all([]) == True
If you want to go with the opposite, your property becomes more complicated.Mathematical definitions are somewhat arbitrary. It's up to us to choose definitions that make sense in our contexts. A general desire to make the resulting systems simple and uniform worked out well for many, many context. Slight detour: that's also why defining 2 - 5 to have an answer is a good idea! Negative numbers were seen as a bit suspect, but they behave perfectly sensible. Same for complex numbers. But: still we generally leave 0 / 0 undefined, because no answer would lead to a satisfying system. |
But whenever I've tried to explain things like this to people, I've found so many just don't seem to see the issue, or to remotely care if they do. Their intuitive responses tend to be:
- It's an obscure issue, it's never gonna come up.
- Oh, well I mean it's obviously your fault for calling it that way with that implicit assumption. Why would you think that?
- Well it's the caller's responsibility to read the documentation/look at the source/test the code before they use this function, not my problem to try to fit it into every mathematically possible use case.
I feel like the notion of putting some more thought into what seems like an elementary API so that these issues don't come up and trip up users in the first place seems like a completely unjustifiable academic effort to them, if not an outright foreign one. Have you found any effective way to try to communicate stuff like this and hopefully actually convince people?