6 ms·
Definitely for prototyping, as someone with years of 'advanced' C/C++/Python experience, and someone trying to learn Rust, I'm finding Rust's 'opinionated' ways
by berkut 5y ago
Definitely for prototyping, as someone with years of 'advanced' C/C++/Python experience, and someone trying to learn Rust, I'm finding Rust's 'opinionated' ways of doing things very painful for things like fast prototyping, where you need to impl 'default' traits on structs, or create builders (which is almost as bad as C/C++'s split of declaration and implementation in that you have tightly-coupled things in different parts of the code.), sticking unwrap() everywhere to not handle all errors correctly at this stage, etc, etc.
i.e. you don't really know what you want, seeing what works, how the data could be organised, refactoring in the early stages, and so much is in flux at this stage, the compiler's warning about all sorts of things, but I don't want to fix them as it might be a waste of time at that stage if you change things yet again, so just end up shoving:
#[allow(dead_code)] above all enums or something, so I can actually see errors within all the warnings.
Once you move past the prototyping stage on to full on production coding, I totally buy that in a lot of cases, the safety that Rust provides (if it compiles, it will almost certainly either panic or work, ignoring logic bugs), is a big win, but I'm not convinced yet for experimentation when prototyping...
- littlestymaar 5y agoI personally love Rust for prototyping for one particular reason: even if it's not as quick as what you'd do in dynamic languages (JS for me, for most people it would be Python) it comes with an enormous benefit: iterating on your prototype several times until you eventually reach the final version is much, much quicker than in any other language I know, simply because the compiler will catch almost any mistakes you make during your refactoring. So, The first draft is going to take like twice as long, but every subsequent iteration on your prototype will be much faster. I find the payoff time to be pretty quick (like one or two iteration are often enough), but obviously if you're doing a true one-shot that you're never gonna touch again, it won't be worth it (that being said in my experience, such situations are pretty rare and most one-shots end up being way more than what they where supposed to in the first place).
- berkut 5y agoYou can argue that (and I'd generally agree in most cases above a certain complexity size) about dynamic vs any static language though?
- littlestymaar 5y agoYes, it's exactly the static vs dynamic trade off, but with one of the best static programming language design. C++ is probably at the other end of the spectrum since it's too easy to accidentally cause a memory error during refactoring. C# and Java are a bit in-between, the automatic memory management limits the footgun, but the type system is much less powerful than Rust's one so there still a lot of issues that can come during a refactoring. I have only very limited OCaml experience and no Haskell experience but I think you'd have most of Rust advantages with those, except the thread-safety part which is my favourite part of Rust but is also situational.
- colonwqbang 5y agoHaskell is quite thread safe, I suppose it is at least as good as Rust in this respect. Immutability by default and garbage collection really help to cut away the ceremony around threading.
- tialaramex 5y ago> I suppose it is at least as good as Rust in this respect. (Safe) Rust has Data Race Freedom, which means you get Sequential Consistency. As I understand it, Haskell does not promise you data race freedom, so, if you mistakenly implemented a data race now you don't have Sequential Consistency and now you can't reason about non-trivial programs at all. I think Haskell, like Java, and unlike C or C++, promises you still get a meaningful program if you have a data race, but it may be tricky to debug the mess. Edited to expand: Suppose you're writing a program to process 16GB of data, the result will be a floating point value between 0 and 100.0 as a result of this processing. You realise it's embarrassingly parallel and so you spin up 16 threads to solve the problem in parallel on your CPU cores. Mistakenly instead of processing 1GB per thread, you process the same 1GB on all sixteen threads, the processing involves a lot of twiddling data, and so now it's full of data races. What is the result of your buggy program? In Rust, the program doesn't compile, or depending how you wrote it, exits immediately reporting that you can't go around processing the same data from different threads. In C or C++ maybe it deletes all your data, more likely it simply exits instantly with no result, spins forever, or outputs something completely spurious. In Java you might get an Exception reporting that you mustn't do this, but you might get a bogus but real looking answer like 46.2 now good luck figuring out why. I don't know for sure about Haskell, but I think you get a similar situation to Java minus the exception.