3 ms·
I disagree. The main difference in social dynamics of Go and Rust projects is that Rust forces you to model more of your domain upfront. This is a good thing, i
by pkd 4y ago
I disagree. The main difference in social dynamics of Go and Rust projects is that Rust forces you to model more of your domain upfront. This is a good thing, in my experience, even if it takes a little bit longer to get going because you end up with a more accurate picture of what your data looks like. Most importantly it provides you the tools to enforce the data model in ways that Go does not. It definitely lacks Go's many footguns too.
Of course writing async code in Go is easier because of goroutines, but apart from that technically they are so different that it is a waste comparing the two.
- verdagon 4y agoForcing you into a model up-front can be good, but only if the model is a good one for the situation. It must have as many constraints as the situation calls for, and no more. Unfortunately, the borrow checker forces two extra constraints which often have little to do with the situation: - No shared mutability. This is an unrealistic constraint; our world calls for shared mutability all the time. Any time a Go reference becomes an index in Rust, you're experiencing this mismatch. - Single ownership (in the C++ and Rust sense). Most things can be phrased in terms of single ownership, but not all things should be, and it has a cost. Rust offers you tools to enforce those constraints, but those constraints are often artificial complexity and shouldn't have been added to a situation to begin with. Same with async/await. They solve a self-imposed problem that e.g. goroutines show us don't need to exist in the first place. We like these mechanisms because they make the program faster, but most of a program doesn't need to be fast. Only the hot path needs to be optimized, the rest of the program should be simpler, more flexible, more decoupled, and have less constraints. (This is one of the reasons some domains should use Rc and RefCell more and our community should stop vilifying them: they help provide flexibility to balance the borrow checker's constraints.) That said, this problem really only arises when one tries to use Rust in a domain it doesn't fit well. There are some domains which do fit the borrow checker's constraints really well, and they become benefits rather than sources of artificial complexity.
- josephcsible 4y ago> No shared mutability. This is an unrealistic constraint; our world calls for shared mutability all the time. Any time a Go reference becomes an index in Rust, you're experiencing this mismatch. Isn't the ease with which a reference can be replaced with an index evidence that you usually don't actually need shared mutability?
- verdagon 4y agoIt can often be quite a pain to use an index. From further up: > For example, in Rust, we often have to use an index or an ID where a regular reference would do in Go. We need to do extra refactoring of function signatures to pass collections down the call stack so we can then use that index/ID... and then find we can't modify a function signature because it's a trait override, and resort to tricky workarounds. In Go, we just use a reference. That choice is decoupled from memory concerns. The problem is that you can't just dereference an index, you instead need all your callers' callers' signatures to take in the collection, causing a minor refactor shock wave in some cases. If that runs into an unchangeable signature (like a trait override, or a public API), it's pretty much game over and you're back to the drawing board. If you're making CLI program or small server, this might not hurt that much. In larger programs, the extra refactoring from this constraint can be quite costly and disruptive.
- MrJohz 4y agoI don't think I understand that example. If I understand correctly, the issue is the question of exclusive mutability, which is why you can't pass the mutable reference itself around. But for some reason you can pass around a mutable reference to the collection and an index? That seems surprising: theoretically, if you have a mutable reference to a collection, you can always transform it into a mutable reference to some subset of its children. Or is this a lifetimes issue, where the lifetime of the individual reference might be longer than the lifetime of the collection as a whole? In that case, it might be that the lifetime annotations aren't correct, or that the code is wrong in the first place. I get the idea that you can't change public APIs and function signatures, but that's true in pretty much every language.
- divs1210 4y ago> No shared mutability. This is an unrealistic constraint; Hard disagree. It is impossible to safely use shared mutable state b/w parallel processes. See how DB isolation levels work - serializable is the only safe way to go if your processes do anything conditional on the current state. To parallelize, you have to partition the DB which is kind of a cheap way to split one physical DB into separate logical DBs. So even DBs - the largest shared mutable states we have - are also not really shared mutable states. They need to be broken down into unshared mutable states to be useful. Shared mutable state is a smell both at the code level and system level.
- verdagon 4y agoJust because shared mutability is sometimes inconvenient for parallelism doesn't mean it's a good idea to outlaw it everywhere. That's like saying "inheritance makes some things easier, so let's use it everywhere we possibly can". Also, you can still apply mutability restrictions at the region/thread/process level. You don't need to apply it to every single object, which would lead to the drawbacks discussed above. If you want to learn more about it, take a look at what Pony is doing.
- pkd 4y agoI think if this comment accurately describes your philosophy then Rust may not be the language for you. This is not a criticism, just an observation. Bryan Cantrill talks about this in "software as reflection of values" [1]. Safety without a runtime is Rust's primary super power, and it fully commits to it by not allowing for affordances that compromise safety as much as possible. If this is simply accidental complexity for you then I am not sure Rust will ever evolve to satisfy you? If you/your team thinks Go makes better tradeoffs there then it's perfectly fine to use it instead - I would say it's even the right choice as IMO, these things matter as much for social dynamics as they do for technical reasons. [1]: https://corecursive.com/024-software-as-a-reflection-of-values-with-bryan-cantrill/ https://corecursive.com/024-software-as-a-reflection-of-valu...
- socialdemocrat 4y agoSo Rust force you to do waterfall design? Sorry just had to tease about that as a dynamic language fan. I am much more in the LISP school of thought, believing in growing software through iteration and exploration, for much the same reason I think lean project development has been more successful. The problem is that so much of the time when you are building something you don't really have a clear idea of what you are doing, but you build and understanding as you experiment and iterate. I do writing professionally now and have much the same experience. It is hard to plan exactly what you will write in detail. So much of the greatest ideas materialize as you write. Both writing and coding is IMHO a thinking process. On the other hand I fully accept that us developers are all different in how our brains work. But I have seen when working with people much smarter than me how much they get stuff wrong and waste time by trying to excessively plan before fully understanding the problem. Stuff I notice I solve easily by taking an experimental and iterative approach. One small concession: I think JavaScript is awful and Ruby projects tend to end up as a mess. I am mostly a Julia, Lua and Go fan. So I kind of learn towards languages which are a bit in between dynamic and static.
- pkd 4y agoRust does not prevent you from changing the model through iteration - it simply makes you explicitly think about it each time you are making changes. That is not against lean/agile way of working. I have worked on one of the largest Ruby monoliths around and I love Ruby, but I also appreciate that Rust can cut through some class of problems that you can't with Ruby (similarly it is much easier to bend Ruby to your will than Rust).