4 ms·
Immutable data does not necessarily let you answer the "what state does this value hold" question easier than mutable data. Imagine you've got an immutable Lis
by UncleMeat 4y ago
Immutable data does not necessarily let you answer the "what state does this value hold" question easier than mutable data.
Imagine you've got an immutable List. x.append(blah) does not mutate x but instead it returns a new list with blah at the end. If you want to know the state of this new list, you need to know the state of x. You still chase a chain of operations to figure out what your data can look like at some program point.
You get the advantage that mutation cannot be hidden inside of functions, but this is achieved just fine with "const" or whatever.
- agumonkey 4y agoIf your logic is about differentials then code around differentials. Which is also one value of FP. This is, IMO, what lead to timetravelling stuff like redux.
- sodapopcan 4y agoBut you do know absolutely for sure that you aren’t accidentally changing some other reference to x.
- XorNot 4y agoI feel this is an overblown problem. The number of times this has been the cause of a bug for me in the last 5 years is zero. Avoiding shared state mutation isn't especially hard in imperative languages: when it happens it's because you're dealing with another constraint - i.e. memory size or wanting to avoid copying due to speed constraints. What is a constant problem is when it turns out you have the wrong value going into the wrong thing: and that's either a logic bug where your inputs are all fine, or a function which is returning the wrong thing. Debugging this problem isn't helped by avoiding mutation really: you're still going to be stepping through every line and checking function results (and a lot of functional styles are really annoying like this - z(y(x(a))) x(a) y z if you're allowed a point free style might save some space, but usually a debugger has no idea how to show you the intermediate results).
- layer8 4y agoAccidental mutation doesn’t happen very often. But when the type system doesn’t distinguish between mutable and immutable values, it becomes hard to reason locally about the code. You never know for sure if that value that looks like it shouldn’t be mutated isn’t maybe mutated after all under some circumstance five function calls away. Or, conversely, if you add a mutation somewhere, it can be difficult to exclude the possibility that some code elsewhere relies on that value not changing. Instead of being able to prove the correctness of some local piece of code, or some locally applied change, it remains merely a good guess, unless you maybe do full-program analysis. That for me is the actual benefit of immutable types — you can sensibly reason about them without having to defensively copy them all the time. I’m in favor of some statefulness, by the way, not a fan of pure FP languages.
- LegionMammal978 4y ago> But when the type system doesn’t distinguish between mutable and immutable values, it becomes hard to reason locally about the code. You never know for sure if that value that looks like it shouldn’t be mutated isn’t maybe mutated after all under some circumstance five function calls away. I don't think that mutability has to be an inherent property of a value: it's really a description of how a value can be accessed. Personally, I'm partial to the model used by Rust, where you can either have shared immutable access to a value, or exclusive mutable access to a value, and you can temporarily loan out your access to another function with a strict deadline (a "lifetime"). Together, this means that you can call a function granting it mutable access to your value, and be confident that the called function is the only thing in the world that could have modified the value. I'm surprised by how this "controlled mutability" solution never seems to come up in discussions of imperative vs. functional programming. Perhaps it has to do with how mind-boggling the borrow checker can appear coming from most other languages.
- Tainnor 4y agoYou may have worked on better codebases that I have. I have seen plenty of "let's write that stuff to a global or thread-local variable because" which makes code harder to understand, test setups harder and may even lead to subtle bugs.
- kag0 4y ago> Immutable data does not necessarily let you answer the "what state does this value hold" question easier than mutable data. Yes, it does. You're right that you still have a chain of operations to figure out first. But with mutable data you need to do that, as well as know when you're looking at the data, and what else is running in the system that has access to that data. It doesn't grant superhuman insight into program state, but it is orders of magnitude simpler than mutable data (perhaps several orders depending on the scope of the data).