3 ms·
It's also a matter of performance. Functional non-mutating patterns in JavaScript and Python can be substantially, sometimes catastrophically, less performant t
by nerdponx 4y ago
It's also a matter of performance. Functional non-mutating patterns in JavaScript and Python can be substantially, sometimes catastrophically, less performant than the procedural/imperative mutating equivalents. All functional programming languages that I know of which have decent performance rely on an optimizing compiler to some extent, and/or core data structures that have been optimized for immutability.
- smitty1e 4y agoPython bogs down where there is excess use of the dynamic aspects, e.g., a large list comprehension. Go with a generator, and watch that list be more kind to the resources.
- chaorace 4y agoThe thing that really irks me is that the generator pattern doesn't have to be an OO-first feature. Observable streams[1] work with the same basic foundation and those are awesome for FP. It's really frustrating that standard libraries are so eager to adopt generators without taking that last step into supporting functional stream consumption. [1]: https://reactivex.io/ https://reactivex.io/
- nerdponx 4y ago> Python bogs down where there is excess use of the dynamic aspects, e.g., a large list comprehension. Go with a generator, and watch that list be more kind to the resources. This is a micro-optimization and it's not always true. Generators usually use less memory, but list comprehensions can actually be faster because the memory gets allocated all at once and the loop is performed internally inside the interpreter, instead of the generator possibly being consumed as a slow top-level loop. I was talking about examples like making a copy of a list/dict/object instead of replacing elements in-place, or using a stack of map/filter operations instead of a single-pass for-loop with dynamic programming.
- smitty1e 4y agoFair point, especially in the case of network-bound or disk-IO intensive work.
- chlorion 4y agoPython supports generator comprehensions too!
- pmarreck 4y ago> Functional non-mutating patterns in JavaScript and Python can be substantially, sometimes catastrophically, less performant than the procedural/imperative mutating equivalents What portion of this is due to the fact that you're using a functional pattern on an imperative language? For example, none of those attempts can take advantage of any underlying purely functional data structures (see: Erlang/OTP/Elixir, or Clojure)
- chaorace 4y agoCase in point: Tail Call Optimization has been part of the JS spec since ES6, but remains completely unimplemented in all mainstream browsers/engines besides Safari[1]. For all but the most predictable inputs, you're pretty much forced to use loops due to potential overflows in situations where recursion might otherwise be preferable. More fuel for the pyre: async Iterables cannot be consumed as a piped stream. You must use the for await construct, which is a shame considering the FP niceties that the Array type already provides for more traditional lists. Once again, one is forced by the API to use an imperative construct unless they specifically want to invite trouble by converting it into an Array (... and potentially choking in the process) [1]: https://kangax.github.io/compat-table/es6/ https://kangax.github.io/compat-table/es6/