Why should the out of bounds behavior be different depending on the semantics of the second parameter?
Because if you want to slice to the end you can just ask for the source's length which is free in most languages (it's not in C or in list-based languages), whereas the "result length" version is either going to have to be computed from the collection length or it's a constraint. In the latter case especially it's annoying to have to do weird computations on the basis of length in order to clamp your existing constraint in case the result would already fit.
Re:Strict APIs vs. Forgiving APIs
by misterdata on Wednesday October 28, 2020 @12:26PM
(#24920693)
Only if the stricter one really requires you to use it differently (e.g. because of checked exceptions). If not you will have to guess for each function if it is strict or not, which potentially causes even more trouble if you get it wrong.
Well, that's one of the reasons why I sometimes myself writing unit tests for the 3rd-party library functions: did I read the docs right? What about some obvious yet still undocumented edge cases? With particularly convoluted APIs those tests sometimes actually end staying in the project's tree.
But if the semantics is "substring(int start, int length)", then I prefer the partial forgiveness for the length parameter: if start + length > len(s), then assume length was actually len(s) - start; but if length < 0, still throw an exception.