3 ms·
Purity is a question of mutability, nothing more. If the function mutates its arguments (or its closure, or its global environment), it is impure. Any useful pr
by brundolf 6y ago
Purity is a question of mutability, nothing more. If the function mutates its arguments (or its closure, or its global environment), it is impure. Any useful program will of course need to do these things at some point, but there's a lot of logic that just goes from A -> B (or A, B, C -> D, or whatever), that doesn't need to concern itself with these things, and should be insulated from them. There's nothing inherently impure about taking large data structures as arguments, though it does make it trickier to enforce immutability in most languages (compared to primitive values).
It's worth noting that it's entirely possible to write "pure methods". Unfortunately most languages don't really let you a) have mutable structures, and b) write enforced-immutable methods on them. Rust is the only one I know of: a method can take a &self instead of a &mut self, which prevents it from mutating self (recursively, which requires knowledge about ownership unless your language is 100% immutable like Haskell or Clojure, which is why this feature is so rare). What I tend to do in other languages like JavaScript, C#, or Python is to use property-getters as a convention that strongly suggests purity; unfortunately that's about the best you can do.
In multi-paradigm languages the decision on whether to make something a pure "getter" method or a standalone function is mostly one of aesthetics. Standalone functions give you a bit more flexibility in use, but sometimes the foo.prop syntax is more readable.
- steveklabnik 6y agoInterior mutability allows you to mutate behind &self.
- brundolf 6y agoYeah true, though I think of that as a bit of a trap-door along the lines of unsafe { }. There's still a reasonable guarantee under "normal" circumstances.