Immutability is very helpful, and the connection between values and identity is illuminating. But there have been very important developments in programming languages since this post/page was written: notably, the introduction of "borrow checking" (exemplified by Rust's implementation). Borrow checking has a very significant positive effect on the sustainability of imperative code, which makes the claim that "imperat…
So if I have mutable array in rust in state A and I start writing state B i to it from the back end in one thread, and reading the state A from the front in another thread - am I guaranteed to read actual state A or will I read a mix of A and B?
Clojure’s Approach to Identity and State (2008)
51–60 of 69 posts
Re: Clojure’s Approach to Identity and State (2008)
#52Earlier quoted context omitted.
So if I have mutable array in rust in state A and I start writing state B i to it from the back end in one thread, and reading the state A from the front in another thread - am I guaranteed to read actual state A or will I read a mix of A and B?
The borrow checker does not allow that, it will complain "error[E0502]: cannot borrow `vector` as immutable because it is also borrowed as mutable".
Re: Clojure’s Approach to Identity and State (2008)
#53Earlier quoted context omitted.
The borrow checker does not allow that, it will complain "error[E0502]: cannot borrow `vector` as immutable because it is also borrowed as mutable".
that in my mind is classic example of how immutable approach saves you from the problem of reading inconsistent world. just like assembly registers, cache lines or struct field alignment, having to think about possibility to read the world inconsistently should not be "generic engineer's" job. it should be considered low level. there are more important things my brain has to be occupied with - like doing my actual jo…
Then, do not mark your variables as mutable. This error only happens if you use `let mut variable_name = ...`
AFAIK, `let var`, e.g. immutable variables, behaves the same as in clojure.
Re: Clojure’s Approach to Identity and State (2008)
#54Earlier quoted context omitted.
that in my mind is classic example of how immutable approach saves you from the problem of reading inconsistent world. just like assembly registers, cache lines or struct field alignment, having to think about possibility to read the world inconsistently should not be "generic engineer's" job. it should be considered low level. there are more important things my brain has to be occupied with - like doing my actual jo…
> but i just don't ever want to see an error like that Then, do not mark your variables as mutable. This error only happens if you use `let mut variable_name = ...` AFAIK, `let var`, e.g. immutable variables, behaves the same as in clojure.
default behavior should be safe and simple to use, dangerous behavior should be hard to reach and inconvenient to use.
Re: Clojure’s Approach to Identity and State (2008)
#55Earlier quoted context omitted.
The borrow checker does not allow that, it will complain "error[E0502]: cannot borrow `vector` as immutable because it is also borrowed as mutable".
that in my mind is classic example of how immutable approach saves you from the problem of reading inconsistent world. just like assembly registers, cache lines or struct field alignment, having to think about possibility to read the world inconsistently should not be "generic engineer's" job. it should be considered low level. there are more important things my brain has to be occupied with - like doing my actual jo…
Re: Clojure’s Approach to Identity and State (2008)
#56Earlier quoted context omitted.
> but i just don't ever want to see an error like that Then, do not mark your variables as mutable. This error only happens if you use `let mut variable_name = ...` AFAIK, `let var`, e.g. immutable variables, behaves the same as in clojure.
"anything that is legal according to compiler will eventually make it's way into the codebase" (approximately quoting Carmack here) default behavior should be safe and simple to use, dangerous behavior should be hard to reach and inconvenient to use.
I understand your point, but to me that is exactly the case. It requires the extra "mut" (harder to reach) and is inconvenient to use (more compiler errors).
My point is; Rust gives you the choice. If you need mutability due to performance, or something like that, you can have it (at the cost of simplicity and convenience).
Also, "dangerous behavior" is not allowed, in this example threads sharing mutable and immutable reference to the same object.
Re: Clojure’s Approach to Identity and State (2008)
#57Earlier quoted context omitted.
that in my mind is classic example of how immutable approach saves you from the problem of reading inconsistent world. just like assembly registers, cache lines or struct field alignment, having to think about possibility to read the world inconsistently should not be "generic engineer's" job. it should be considered low level. there are more important things my brain has to be occupied with - like doing my actual jo…
If you wanted to use an immutable data structure, then you’d just use one. The im crate is a good example.
top comment claim is that clojure's approach to identity and value-semantics is somehow superseded and invalidated by rust's ownership and borrow checker, which is just too much koolaid. example i gave illustrates that given rust's default tools somebody will either have to deal with unnecessary low level errors (has nothing to do with high-level business logic of "i need this array to have new data") or will find a way to write incorrect code. none of that will happen given clojure's default tools.
Re: Clojure’s Approach to Identity and State (2008)
#58Earlier quoted context omitted.
It's proprietary for the time being; but in short, it is more straightforward than I thought it would be. We are working with LibreOffice Calc ODS sheets, which are pretty terrible as a format (since the references are not normalized in the formulas, they can't repeat them even when they behave identically, and they duplicate most of the XML namespaces in the attributes). We parse and normalize the references from A1…
Interesting project! Could you explain what you mean by "since the references are not normalized in the formulas, they can't repeat them even when they behave identically"? Do you mean the normalization from A1 to R1C1 that you mention later in the post or something else?
Re: Clojure’s Approach to Identity and State (2008)
#59Earlier quoted context omitted.
"anything that is legal according to compiler will eventually make it's way into the codebase" (approximately quoting Carmack here) default behavior should be safe and simple to use, dangerous behavior should be hard to reach and inconvenient to use.
> dangerous behavior should be hard to reach and inconvenient to use I understand your point, but to me that is exactly the case. It requires the extra "mut" (harder to reach) and is inconvenient to use (more compiler errors). My point is; Rust gives you the choice. If you need mutability due to performance, or something like that, you can have it (at the cost of simplicity and convenience). Also, "dangerous behavior…
Re: Clojure’s Approach to Identity and State (2008)
#60Immutability is very helpful, and the connection between values and identity is illuminating. But there have been very important developments in programming languages since this post/page was written: notably, the introduction of "borrow checking" (exemplified by Rust's implementation). Borrow checking has a very significant positive effect on the sustainability of imperative code, which makes the claim that "imperat…
You can avoid this complexity by killing either one of the adjectives: shared OR mutable. Immutability is generally pitched as the only way to solve this problem, and it is definitely a valid solution, though not the only one. The other dimension to cut off is sharing. If mutable data is not shared, its mutability also becomes mostly irrelevant.
Rust and Swift both support immutability as well as unshareable references. In Rust’s case, it’s more like organized sharing that prevents simultaneous mutation. In Swift’s case, structs truly can only have one reference.