7 ms·
This is incredibly vague. There is no "set of rules" that just magically works without thought. There is just SOOOO much that can go wrong. But one general rul
by marta_morena_28 6y ago
This is incredibly vague. There is no "set of rules" that just magically works without thought.
There is just SOOOO much that can go wrong. But one general rule crystallizes itself pretty quickly:
DO NOT EVER MUTATE STATE!
I.e. when you write concurrent code that builds on state mutation, you are opening Pandorra's box. If you want concurrency that people can understand and maintain, write immutable, functionally pure code (same data in, same result out, no exceptions). That is relatively easy to police and enforce, while still flexible enough to solve most use cases. It may however, not be the most performant.
- maxeonyx 6y agoI like to think of mutation as a performance optimisation. Correctness first, then optimisation. Unless performance is a problem, don't ever mutate state.
- nyanpasu64 6y agoMutation is not merely a performance optimization, but makes code more concise and expressive. Mutation makes things like `cfg.tabs[2].title = "Suspended"` possible to write in one line. Trying to achieve the same thing with only immutable data structures forces you to clone title, then clone cfg.tabs[2] with a new title, then clone cfg.tabs with a new [2], then clone cfg with a new tabs.
- waynesonfire 6y agoYou don't lose conciseness with mutable state. What you seem to think is lost can be regained through abstraction. Just think about the complexity behind the assignment operator, all the way to the logic gates in RAM.
- lmm 6y agoYou don't need mutation to write that expressively; you can achieve the same thing with lenses. With the advantage that if you ever get confused about what's happening you can break the lens down into what it's "really" doing and reason about that, in a way that you just can't with language-level mutation. Syntax shortcuts are good when they're built on a rigorous foundation. But if you build a shortcut directly into the language, you'll never be able to retrofit a reasonable model for how it works.
- blub 6y agoPlease post the lens code here so that we may judge how expressive it is :)
- lmm 6y agoWith zero effort cfg.lens(tabs).composeOptional(index(2)).lens(_.title) set "Suspended" You could certainly define a shortcut to simplify the `composeOptional` part, but doing it explicitly like this makes it clear that we actually have to make an important choice: what do you want to happen when there is nothing at index 2?
- blub 6y agoThank you. To me that seems significantly more verbose, is it possible at least to pack it into a generic function and apply it to most/all assignments?
- lmm 6y agoThe mixing of the array access (which is another piece of language-level special-case syntax) with the properties is what makes it verbose - "normally" you could just do something like config.lens(tabs[2].title) set "Suspended" Admittedly that relies on a macro, but the macro is pretty lightweight syntax sugar - if you wanted to do it in 100% vanilla code you'd need a .lens at every step and a slightly more explicit way to name the "properties", i.e. config.lens(_.tabs).lens(_(2)).lens(_.title) set "Suspended" > is it possible at least to pack it into a generic function and apply it to most/all assignments? I don't quite understand? You can certainly write generic functions that work for any lens whose "target" is a given type.
- nyanpasu64 6y agoI've heard about lenses, but never actually worked with them. This syntax seems to construct a "path" of sorts from the root to a field. What language is this? What type does the `set` operator/keyword return?
- beders 6y agoI suggest you check out efficient mutable data-structures which are safe by default. Clojure and ClojureScript come to mind.
- UncleMeat 6y agoThey are still less efficient. Compare even modern stuff like HAMTs to ordinary sets. Close, but no cigar.
- dragontamer 6y ago> DO NOT EVER MUTATE STATE! This is counterproductive. Mutating state is by far, the most efficient operation on the computer. Copying state means (usually) calling the memory allocator, which (usually) must be done in a sequential manner. There are optimizations to allow memory-allocation to occur in parallel, but... things start to get inefficient (use of thread-local storage, which makes many pointer-indirections, etc. etc.). ------- Why do people program parallel code, despite its overwhelming complexity? Simple: to be faster. That's it. Its an optimization, arguably premature, but the programmer reaching for the "parallel" button is going for optimization for a reason. ------ Sequential code with state-mutations could very well be more efficient than parallel code with tons of unnecessary copies. Registers are fast, L1 cache is fast, etc. etc. Doing an operation, then undoing it (entirely inside of register space) is so incredibly fast, it will make your head spin. ------- 1: Write code. 2. If code isn't fast enough, single-thread optimize it. This usually means mutating state in an intelligent manner. 3. If code is STILL not fast enough, multithread it. You make a copy of the state, and then have multiple threads (each with their own copy of the state) doing... whatever you're trying to do.
- Arelius 6y ago> Mutating state is by far, the most efficient operation on the computer. Really? I mean like pretty much every instruction has separate source and destination addresses/registers, memory caches obviously complicate things, but it seems that processing data from one location to another is the most efficient operation. > Copying state means (usually) calling the memory allocator Sure, I guess if the main conception of moving data around involves not really knowing where it needs to go, and having to figure that out, that's somewhat true. But there are many ways to structure computation that minimizes or avoids allocator usage. > unnecessary copies I think this is the issue, if you have to copy first then do in place mutations, of course it'll be slower, but you can instead structure your entire computation to process your data from one location to another, then all your points about registers, and L1 cache being fast, holds true while still being able to handle immutable data
- dragontamer 6y ago
- jjav 6y ago> DO NOT EVER MUTATE STATE! Mutating state is what computers are all about. You can be super inefficient about it by copying everything on every operation. But avoidance is not the road to optimal solutions.