3 ms·
"Chained folds (map, filter, etc.) immediately within the same expression really should be easy to optimize" In a pure functional language they are. In a non-
by jerf 3y ago
"Chained folds (map, filter, etc.) immediately within the same expression really should be easy to optimize"
In a pure functional language they are.
In a non-functional language with mutation it is much more challenging. Map functions are unconstrained in Javascript which means they can do anything they like with regards to breaking optimization.
This is generally why I'm down on the whole "chain maps and filters" style of programming in languages that aren't designed for it. You are paying more than you may realize if you've never profiled your code and compared. In languages that are designed for it and have the ability to optimize it, by all means, go for it.
The other thing you have to remember is that JITs are time-constrained as optimizers go. They have the advantage of access to real run-time information about how things are being used, but they also have very, very tight time budgets; on the whole the time budget's problems seem to dominate the knowledge advantages. The profiler is not allocated a lot of time to prove that a given function is pure and it's OK to synthesize a composed function rather than run two maps. I don't even know if any JS engine is smart enough to try that. (Input from anyone who knows welcome, I'd be interested to hear either way.)
- ndriscoll 3y agoYou don't need the language to be designed for it or to prove it. Just document it as a contract for the caller. e.g. "the argument to map must be a pure function. For functions with side effects, use forEach. If an impure function is provided, the behavior is undefined." This isn't very different from contracts that require you not to change the length of an array when using iterators.
- jerf 3y agoYeah, I'm imagining trying to push that sort of thing out into the Javascript world, and maybe your model of Javascript programmers is a lot different than mine, but I don't see this going terribly well. In the Javascript world's defense, I don't see this as a practical solution in very many languages at all. I don't think I can name any language that doesn't have a compiler-level enforced definition of "pure function" somehow where its programmers will across-the-board reliably know what a "pure function" is. Much as I hate to lick HN's boots and inflate the already substantial ego we can have here sometimes, do remember that HN is generally populated by the upper echelon of programmers and there's plenty of people out there who would have no idea what this means. I can think of several coworkers over the years. This isn't even an insult in the sense you might think; not everyone programming is necessarily a "programmer" I expect to be super knowledgable about programming. I'm having a major issue right now at work where I've got a data scientist sort of pushed into doing even just a bit of "programming work" interacting with an engineering organization and it has been a freaking nightmare, and I can't even really complain because while they are wielding Python, programming is really just a side task in the world of data analysis. They may be able to program in Python but they have no idea about performance, super focused understandings of optimizations (at best, sometimes it's just zippo), an incredibly surface level understanding of Python syntax, etc. And why not? It's not actually what we're paying them for.
- ndriscoll 3y ago> In the Javascript world's defense, I don't see this as a practical solution in very many languages at all. I don't think I can name any language that doesn't have a compiler-level enforced definition of "pure function" somehow where its programmers will across-the-board reliably know what a "pure function" is. IME Scala programmers generally don't have much trouble with this, and the language doesn't do anything to prevent side-effects wherever you feel like putting them. It's just culturally not very common. Similarly, you can use `null` for almost anything in Scala, but it's extremely rare to run into one in code that isn't interacting with Java. But nothing really stops you from using basically any feature as Java++. For your Python programmer, like I mentioned they already have to deal with some form of no-side-effects with for loops: you should not modify the length of a data structure that you are iterating over (`for x in foo`), or you'll get weird/unexpected results (e.g. [0]). You don't need to even go full UB, and could just specify that the order that the arguments to chained folds get called in is unspecified, and that code that needs to care should use `forEach` or a for loop. IME if you're writing in a pipelined map/filter/fold style in the first place, the ordering question just doesn't come up much. With that style it's rare to need to mutate anything yourself because the mutation you need is baked into those loop primitives. [0] https://stackoverflow.com/questions/38003119/what-are-the-rules-for-iterator-invalidation https://stackoverflow.com/questions/38003119/what-are-the-ru...