6 ms·
Stupid question, but will Rust ever have a non strict mode. I'm used to writing C# , Python and JS. Rust seems to be overally punishing
by offtop5 6y ago
Stupid question, but will Rust ever have a non strict mode. I'm used to writing C# , Python and JS.
Rust seems to be overally punishing
- munchbunny 6y agoFor the types of stuff Rust is often used for, the strictness is a feature.
- elliebike 6y agoNo, because that's not really the point of Rust. You make the sacrifice of a "punishing" compiler, and spending more time writing code, but you gain software that's more likely to be "correct", safe, and not leak memory. Really, as in all things computers, it depends what your set of requirements are as to what trade offs you make
- snazz 6y agoAlthough I haven't verified this myself—I'm not much of a Rust wizard—I've heard that Rust's type system and borrow checker allows you to spend less time total, because your debugging time drops significantly.
- ben-schaaf 6y agoVerifying that would be incredibly difficult/impossible but I've personally found that rust has on multiple occasions prevented me from making a mistake that would have cost likely hours to debug that I was instead able to fix in a few minutes.
- matt_kantor 6y agoFans of static type checking use that as a rebuttal against "but I'm so much more productive in $dynamically_typed_language". I've also seen it in discussions about Scala, Haskell, TypeScript, etc. Intuitively it makes a lot of sense, and it jives with my subjective feelings (especially for longer-lived projects), but I'm not sure if there have been any studies to back up that claim.
- steveklabnik 6y agoI am not aware of any studies that definitively show an advantage for static or dynamic typing; there have been ones that didn't provide anything conclusive, and you could argue that the experiment design wasn't representative. https://danluu.com/empirical-pl/ https://danluu.com/empirical-pl/ is a good place to get started on this topic.
- root_axis 6y agoFrom an organizational perspective, the benefits of static type checking are quite obvious. I'd go so far as to say it's a software engineering best practice to prefer languages with static types when building new software. The reason for this is because many, many, many engineering hours are saved at an organizational level by having a compiler that is able to enforce correct data structures throughout the application. Eschewing types for speed is just a form of technical debt that has to be repaid in perpetuity whenever it comes time to maintain or refactor the software, not to mention the fact that every new developer working on the application is now burdened with this debt.
- tptacek 6y agoPerhaps compared to Python, Ruby, and vanilla ES6; there is a class of epsilon-from-typo bugs that modern statically typed languages catch and that force rigorous Python and Ruby shops to waste time writing vast batteries of tests for the most banal functionality in their codebase ("does this setter set?"). Moving from one of those languages to a modern statically typed language can come with a feeling that your programs tend to run successfully as soon as they compile --- certainly they do more often than they would in Ruby. Because the compiler is doing some of that testing work for you. It's a good feeling. But it hasn't been my experience that the extra rigor in Rust's model produces the same boost from Java or Go; in fact, my first-run experience with Rust is generally less reliable than Go; there are a few more things that can go wrong with a Rust program and slip by the compiler. Which is what you'd expect; Rust isn't garbage collected, so the programmer has to do the garbage collection, and every program is responsible in some sense for designing and implementing that part of its own runtime. There are things you can get wrong there that GC'd languages don't make you bother trying to get right. And, of course, if you take the time to get your per-program runtime really right, there's a performance gain to be had from doing so. It's all tradeoffs.
- burntsushi 6y ago> Which is what you'd expect; Rust isn't garbage collected, so the programmer has to do the garbage collection, and every program is responsible in some sense for designing and implementing that part of its own runtime. This seems like a really odd thing to say in at least two dimensions. Firstly, I would say that "the programmer has to do the garbage collection" isn't an accurate way to describe Rust. Secondly, and particularly in comparison with Go, Rust's RAII applies more universally than Go's garbage collection. How many times have you seen a missing defer or a defer inside of a loop? I've seen both quite a bit. But those bugs basically don't happen in Rust precisely because the programmer almost never needs to deal with destruction directly. It's done automatically by the compiler. As to the broader point, I would very strongly oppose the notion that Rust is less reliable than Go. While I don't think I would argue that Rust gives the same boost over Go that, say, Java or Go give over Ruby (that's a tough argument to make anyway, even if I agreed with it), I would say there is a meaningful boost. But that's a tough argument to make too. Aside from the obvious bits (nil errors and forgetting to check errors), for me, it basically comes to my belief that Go punishes its practitioners for abstraction. I wrote a bit more about that here: https://users.rust-lang.org/t/what-made-you-choose-rust-over-go/37828/7 https://users.rust-lang.org/t/what-made-you-choose-rust-over...
- sk2020 6y agoCuriously, I’ve never seen anyone in forums take this premise to its logical conclusion and advocate the use of a language which has a much more powerful type system than Rust does, like dependent or refinement types. Haskell, Scala, Idris, and others (even Python with crosshair!) natively or with extensions support enforcing some very sophisticated constraints on a program. Tagged unions and interfaces are hardly the limit of what’s possible. However, I don’t think cutting edge type systems, theorem provers or other sophisticated tools for program validation have demonstrated enough business value to receive widespread adoption outside of only some (albeit very important) market sectors. Really, I think most argumentation comes down to “the type system of the programming language I want to use anyway is the right one, and everything else is wrong”.
- munchbunny 6y agoI lump this into the category of learning how to best apply your tools to the right situations. If I'm slinging together an internal CRUD app, the extra time thinking about types probably will slow me down because the major risks aren't really type problems. But if for example I'm working on something in a game engine, being able to use the language and compiler to enforce assumptions/invariants at compile time is really useful.
- jcelerier 6y agoThere's some tradeoff there though. I'm doing most of my dev in C++ and run all the time with ASAN / LeakSanitizer. I have a leak-causing mistake, what, twice a year maybe ? Definitely not something worth loosing sleep over. The much bigger problems imho are not really tractable. e.g. consider something that does: struct server { std::vector<requests> m_requests_to_process; boo m_running{true}; void on_web_request(request req) { m_requests_to_process.push_back(req); } void process_pending_requests() { while(m_running) { for(auto req : m_requests_to_process) { do_stuff(req); } // oops, forgot to clear } } }; there's no "leak" in the OS sense as everything will be reclaimed upon server::~server... but your memory usage will be strictly increasing. Can Rust detect those cases ? As in my experience this is the most common leak pattern (of course not in a simple example like this, but when your "server" architecture starts being split across multiple threads and source files...
- steveklabnik 6y agoRust does not attempt to stop leaks. It does make it less likely to happen, but completely preventing them is not even on the table. This particular case might be because you would probably consume the vector in the loop, which would free, but you could absolutely write the exact same code in Rust with the same end result.
- GlitchMr 6y agoRust doesn't prevent memory leaks. However, it may help in this specific case. In your example you are iterating over `m_requests_to_process`. As you are using `auto` instead of `auto &` it automatically clones the elements of a vector. In Rust, it's not possible to clone an element by accident. Objects are moved by default (think `std::move`) and if you want to clone instead you need explicitly use `.clone()`. If `do_stuff` function takes ownership of a request (as in, if it takes `Request` parameter and not `&mut Request` parameter) than the problem will be pointed by Rust, and so the compiler wouldn't allow you write code like this forcing programmer to write code that removes elements from the list to take ownership of them. For example: for req in mem::take(&mut self.requests_to_process) { do_stuff(req); } `mem::take` (https://doc.rust-lang.org/std/mem/fn.take.html https://doc.rust-lang.org/std/mem/fn.take.html) replaces an object behind a mutable reference with a default value for a given type (empty vector in case of vectors) and gives you an ownership over vector.
- ben-schaaf 6y agoFor "non strict mode" meaning bypassing the borrow checker, rust already has that and it's called "unsafe". And if by "non struct mode" you mean not having manual garbage collection then you've already got that either as `::leak` letting you leak memory or various GC implementations like https://github.com/Manishearth/rust-gc/ https://github.com/Manishearth/rust-gc/.
- offtop5 6y agoSo I could mark my code unsafe and be able to prototype faster , then later when it's time to ship , remove unsafe and fix the smaller issues ?
- hermanradtke 6y agoOne must write structure a program in a way that is compatible with the borrow checker. It would probably require a rewrite to make unsafe code that was purposefully ignoring the borrow checker then pass the borrow checker. Keep working at it. After a while you start to realize the patterns that work. Now, I can prototype in Rust pretty fast.
- steveklabnik 6y agoIn theory yes, but in the way you're probably thinking about it, no. Unsafe doesn't turn off checks, it adds features that are unchecked. So you can't just toss in unsafe blocks and get the compiler to let you do whatever you want, you have to actually write different code.
- bryanlarsen 6y agoI don't have much experience, and thus might be wrong, but one thing I've internalized is that it's often better to just use Rc<T> (reference counted smart pointers) or a garbage collector to make forward progress rather than fight the compiler trying to get lifetimes straight. You can make it more efficient later, but it's often not to worth the bother.
- ywei3410 6y ago
- deleted 6y ago[deleted]
- andrewzah 6y agoI think looking at it as "punishing" is the wrong mentality. Rust has very strict checks, and we -want- those. That's why we're using Rust in the first place. I -could- use a more convenient / lenient language like ruby or golang but I generally wouldn't prefer it unless the use case made sense. You end up "paying" in different ways later down the line as your codebase grows in complexity. In my experience, the rust compiler is extremely helpful and most issues I had went away after reading the rust book. [0] [0]: https://doc.rust-lang.org/book/ https://doc.rust-lang.org/book/
- tptacek 6y agoI take your point, but Ruby vs Go isn't a reasonable comparison. Rust is a lot stricter than Go, by necessity (no GC), but they're both statically typed languages.
- andrewzah 6y agoBoth are significantly less "strict" than Rust. Anyway, it's just an example.
- tptacek 6y agoThe difference between {Rust, Go} and Ruby is almost entirely about rigor. The difference between Rust and Go, on the other hand, is mostly pragmatic: Rust is "strict" about design and implementation details Go's runtime handles for the programmer; there's nothing for Go to be "strict" about. Rust is more rigorous than Go, but to a much smaller degree than Go is over Ruby.
- creata 6y ago> there's nothing for Go to be "strict about" Regarding memory management, sure, but Rust's strictness also handles things that Go doesn't. Two examples are error handling --- Result<T,E> in Rust ensures that you check for errors before using a result --- and thread safety --- the borrow checker prevents many synchronization errors that Go doesn't catch.
- pornel 6y agoIt probably won't. Rust's unique selling point is in a combination of safety, performance, and minimal runtime (no garbage collection). The most difficult aspects of Rust are a direct consequence of safe minimal-overhead memory management, and we don't know how to do much better without adding a GC/runtime or compromising safety. Rust has many quality-of-life improvements that could be transplanted to a more relaxed GC-based language, but that won't be Rust any more. Here are some musings how such language could look like: https://without.boats/blog/revisiting-a-smaller-rust/ https://without.boats/blog/revisiting-a-smaller-rust/ (OT: why OP got downvoted so hard? It's a reasonable question to ask)
- steveklabnik 6y ago> (OT: why OP got downvoted so hard? It's a reasonable question to ask) I also am disappointed that the OP got downvoted. Seems bad.
- offtop5 6y agoA big part of life is accepting people will disagree with you. Ultimately I did get a solid explanation here. If I want a quick, fast and dirty language , Rust doesn't fit the role. I really do love how C# gives me the ability to hack things together quickly, with still stopping me from doing things which simply won't work. Flutter takes this even a step further with the dynamic keyword( C# has dynamics too , but they aren't as robust ). I can write function calls with dynamics which is great for prototyping. Eventually bad things will happen if you use dynamics in every single call , but it helps me get started. I definitely understand why many software developers see this as a dumbing down of software engineering, which I would attribute the downvotes to.
- rkangel 6y agoThere is definitely an aspect of the 'the appropriate tool for the job'. We use Python extensively for 'glue' scripts on my project (build, deployment etc.). It's wonderful and convenient for programs that are 10 to 1000 lines long. The result is clear and predictable and maintainable (particularly when compared to a bash script alternative). I would never write a large production app in Python though (having done it a couple of times). The flexibility becomes unwieldy at that scale and you have to have tests that exercise every corner or you'll have problems hours or days into running.
- momothereal 6y agoYou might be more interested in something like Go, which has a less punishing compiler.
- higerordermap 6y agoRust doesn't overlap with the application areas of those languages. It is a complement as systems language to those web / backend / script languages. I too don't like rust evangelism around here. But any developer should know at least one system language, understand algorithm complexity, understand basics about memory management and caches, etc.. And probably it is easier to learn rust than C++ to those with web background.
- root_axis 6y agoThe eagerness of the compiler to point out your mistakes is the quintessential feature of rust, if this is something you don't want to deal with then almost certainly rust isn't the language for you. With that stated, I would encourage you to understand why rust was designed this way and why the strictness of the compiler is actually a major advantage compared to languages like Python and JS where a lack of a type system actually makes the software much more prone to bugs.
- creata 6y agoThe main way to make the compiler more forgiving is to use Rc<RefCell<T>> (and Arc<Mutex<T>> when you need thread-safety) to move borrow checking from compile time to run time. Please avoid doing that, though --- it's ugly, it can be slow, and the borrow checker is usually yelling at you for a good reason. There are also some immature crates for tracing garbage collection in Rust, like rust-gc, which typically has higher throughput than reference counting.
- rkangel 6y agoOne thing you can do is wrap everything in Rc<>. This makes the held object reference counted and you can copy references around as you feel like. This gets you ownership much more like what you would get in a GC language (e.g. C#, Python, JS), but in an opt-in fashion.
- scudd 6y agoIn my experience, I did eventually start to appreciate the compiler forcing me to address things up-front. But as an aside, if you're just trying to prototype quickly, some useful "shortcuts" can be: - Using `Box<dyn std::error::Error>` for functions which need to handle a result - Using `unwrap` or `expect` to easily access Option internal values - Using `unimplemented!()` if I'm trying to mock an API design. This one is nice because it will let you build out the signature including specifying a return type without having to build out the function logic. Obviously these are shortcuts and not production suitable, but can be good to just get some code on the page that compiles
- mamcx 6y agoI have used that langs and much more. Rust was the hardest lang I have learned by a long shot. The first 2 months was kind of miserable (more because I try to build a interpreter that hit some of the hardest stuff on rust, and not knowing how deal with them). In retrospective, I make the life harder: * Thinking like in the other langs I have learned (with exception of my first 2) is enough to just read fast some tutorial and start coding... I relent and pick a book to learn it right. * Start worrying so much about performance, when never before I bothered much (what! this can ALLOCATE!). Now I clone like madman! * Try to fit the OO mentality to Rust. Even in F# I don't fully commit to POCO objects and functions as I do in Rust now. Also, the lacks of polymorphism is what hurt me sometimes (ie: is harder in rust) But now? Rust feel ABSURDLY productive. The thing I notice is how much I refactor stuff now, (even more than in F# that also was a up in this regard). The "punishment" parts is only in my toy interpreter and very small now. For my main project ( a ERP/ecommerce app rewrite from F#) Is great!.
- cute_boi 6y agoSorry but no please. I am already irritated by library in typescript that uses any everywhere :/
- GolDDranks 6y agoYou might enjoy trying OCaml! Most of the "necessary and hard" strictness of Rust comes from not needing a garbage collector. Once you have that, it's a lot easier to provide something rigorous but more ergonomic.
- outworlder 6y ago> Rust seems to be overally punishing There's nothing preventing you from using multiple languages on your app. Say, Rust for foundations and Lua/Python/Scheme/Tcl/Whatever for glue.