5 ms·
The fact that lists are inefficient doesn’t mean that they should be processed in a maximally inefficient way. I would argue the opposite is true. There’s no pr
by jolux 4y ago
The fact that lists are inefficient doesn’t mean that they should be processed in a maximally inefficient way. I would argue the opposite is true. There’s no practical justification for forcing the compiler to allocate a new stack frame when you can get it to use a jump instead.
- yawaramin 4y agoThere is actually a practical justification–simplicity of the implementation. For a data structure not meant to be used for large datasets, why optimize for that use case? In any case thanks to TRMC landing in OCaml 4.14+, it's a moot question, we'll be able to have our cake and eat it too. Doubtless someone will add the annotation to the standard library soon enough: https://v2.ocaml.org/releases/4.14/manual/tail_mod_cons.html https://v2.ocaml.org/releases/4.14/manual/tail_mod_cons.html
- jolux 4y ago> There is actually a practical justification–simplicity of the implementation. For a function that is going to be written once and called innumerable times, this is a bad justification. You should optimize for the consumers of your library, not for yourself. > For a data structure not meant to be used for large datasets, why optimize for that use case? Because it’s not the job of a standard library to be opinionated about how people use data structures. It’s the standard library’s job to do what is asked of it as efficiently as possible. The best implementation would be specialized for small Ns but they don’t do that either. Good to hear about TRMC, I haven’t been a daily user of OCaml since 4.07, but it’s good to hear that they’re addressing some of these pain points. I still think Core and Base are a better starting point for real-world applications in general.
- yawaramin 4y ago> Because it’s not the job of a standard library to be opinionated about how people use data structures. Well, they're not being opinionated about it per se, they're just not supporting (up until now at least) highly-optimized use of lists. There are tradeoffs to consider here beyond what we have discussed in this thread. Check the OCaml forum threads on optimizing list mapping for the various considerations.
- jolux 4y agoYou characterized this deficiency in light of your own belief that lists should not be used, so I was responding to that part that I disagree with. It’s like Python purposefully crippling lambdas to discourage their use. If you don’t think people should use a feature, just don’t add it. Incidentally I agree with you about lists and only meant to use it as an example of a place where the stdlib authors chose a simple implementation over one that does what you expect. As soon as I started reading the stdlib source and seeing things like that, I immediately understood why Core exists and realized I wouldn’t be able to trust the stdlib in production. It violates the principle of least surprise. It’s one thing to do stuff like this in Haskell where it makes sense because of lazy evaluation, it’s another to do it in an eager language which acknowledges the need to make concessions to practical usage.
- yawaramin 4y agoWell, if you bring up Haskell, let's remember that String is defined as a list of Char, and in production most people seem to use a variety of other replacement string types and everyone will tell you not to use Haskell String for any serious production use. Also, > violates the principle of least surprise I suppose yes if you don't read the docs which point out that it's not tail-recursive, and a few lines below a tail-recursive alternative `rev_map` is given.
- jolux 4y ago> Well, if you bring up Haskell, let's remember that String is defined as a list of Char, and in production most people seem to use a variety of other replacement string types and everyone will tell you not to use Haskell String for any serious production use. The point is that this pattern makes sense in a lazy-evaluated language, not that everything Haskell does makes sense. I think it's a less defensible choice than OCaml in most cases. > I suppose yes if you don't read the docs which point out that it's not tail-recursive, and a few lines below a tail-recursive alternative `rev_map` is given. I read the docs and I still disagree with the choice made here. There's no need to include two functions when one will do. This is not pragmatism, it's laziness.