14 ms·
You may call functional programmers who prefer immutable data structures lazy because we want to actually understand what we create, but I don't see how the 10
by askonomm 5y ago
You may call functional programmers who prefer immutable data structures lazy because we want to actually understand what we create, but I don't see how the 10 billion layers of abstractions and state duplications somehow end up making better software.
- josephg 5y agoI agree - I think having 10 billon layers of abstraction is worse for everyone. It’s buggier, more expensive to make and (ironically) often slower in practice anyway; because you can’t optimize what you can’t understand. Java style OO has a lot to answer for. Functional programming is great. What’s not great is loading the entire closure VM environment into my browser - resulting in the software running (in this case) 50x slower. FP is no excuse for making my computer crawl to a halt. And there’s no essential reason FP needs to be slow. For example, look at how well llvm optimizes map/filter/fold in rust. In many cases they’re faster than their imperative counterparts! There are other ways to benefit from immutability that don’t involve burying a garbage collector in useless work. For example, React is a lovely example of immutable ideas, and a fast runtime. I spent a few thousand dollars on a new Mac laptop recently. I wonder what percentage of my clock cycles are going to be wasted due to bad abstractions and inefficient code? Probably most of them. I wish I could take the money I spent on the machine and instead pay people to improve their software. I don’t have billions of cycles per second of actual work to do.
- comma_at 5y ago> What’s not great is loading the entire closure VM environment into my browser There's no VM in clojurescript, it compiles to JS, it is tree-shaken and heavily optimized and minified through Google's Closure compiler. > resulting in the software running (in this case) 50x slower The speedup is not a result of abandoning clojurescript, it's from moving from immutable data structures to mutable arrays and primitives. The same can be done in clojurescript or javascript. I think this is a common misunderstanding, that's why I'm reacting. Nobody claims immutable data structures to be the silver bullet. Computation-heavy parts need to be done in low level code and with primitive types.
- sickill 5y ago> The speedup is not a result of abandoning clojurescript, it's from moving from immutable data structures to mutable arrays and primitives. The same can be done in clojurescript or javascript. More or less, yes. The majority of the perf increase here came from two things: 1. going from immutable->mutable, 2. going from CLJS/JS->Rust in the perf critical part. Doing just 1. would likely improve the performance, but not as much as doing both 1. and 2. Doing just 1. while staying with ClojureScript could potentially be accomplished with transients [0] at the cost of making a major chunk of the code non-idiomatic Clojure. I actually played with transients here before attempting the rewrite, but haven't got too promising results though. [0] https://clojure.org/reference/transients https://clojure.org/reference/transients
- drenvuk 5y agoI'm not sure if you feel attacked or not but you shouldn't. Being lazy is good for programming I think. You should keep in mind that your functional programming base is built on a figurative 10 billion layers of abstraction already. It's just that those abstractions are somewhat well made so you don't have to think about it. Proper abstractions aid in understanding and can ideally be optimized away. Poor abstractions hinder it and slow things down.
- nyanpasu64 5y agoTo me, it is lazy to use immutable data structures in situations where they generate large amounts of garbage and/or result in user-facing GC pauses. (In Firefox, I encounter many slow sites (with or without immutability) with multi-frame pauses, often GC pauses. I think the slowdown is coming from the website and not my extensions.) I believe it's possible to understand the code you create, even in the presence of mutation (though you can no longer store old values for free, and need to use cloning or other approaches). You need to restrict which code is responsible for mutating state (using careful program architecture), and restrict the ability to mutate data while other pointers to the data exist (Rust imposes these restrictions). Interestingly, the Relm architecture is a translation of the Elm architecture (Elm is an immutable language) to Rust code (Rust is a mutable language) which restricts which code is responsible for mutating state, and Rust restricts the ability to mutate data while other pointers to the data exist. Interestingly, Rust unifies immutable and mutable data structures. The im library (https://docs.rs/im https://docs.rs/im) uses the same tree-based immutable data structures as Clojure and such, but exposes an API closer to Rust's stdlib containers (including mutation). However im's performance characteristics are different from Rust's stdlib; clones are shallow and take O(1) time, while IndexMut is slower and copies tree nodes whenever that node's refcount is greater than 1. immer.js (https://github.com/immerjs/immer https://github.com/immerjs/immer) has a somewhat similar API, but a different implementation (I think it uses standard JS arrays and copies the whole thing when you mutate one element).