I really like the safety guarantees offered at compile time, and really do think that we should move away from C-like languages if we ever want to control the tsunami of security flaws, but I can't stop wondering if Rust isn't (perhaps needlessly) complicating things and scaring off (non-C++) programmers.
[1] Sidenote - I find it really fascinating how Rust can also use the stronger static checks to prevent things like race conditions in a way few (/no?) other languages can.
A concrete example that I've run into recently when trying to write C++ code. I figured that, for safety reasons, I needed to make my type be move-only. I then had to spend about two hours trying to figure out why the program was blowing up. The reason was that I was reusing the variable after moving from it, and the compiler never gave any warning (even on -Wall -Werror) telling me that what I was doing was wrong. In Rust, the same situation would be a compiler error.
So you either have a C++ shop where everyone is on board regarding security, with the caveat of third party dependencies, or no one cares and writes something along the lines of C with C++ compiler, without any kind of static analysis.
Relying on external tooling means it usually gets ignored if it is not enforced. After all C's first version of lint goes back to 1979.
Sadly JetBrains latest questionnaire results prove exactly that.
So having safety as integral part of the language semantics matters a lot. Defaults matter.
There was a funny discussion on the Rust subreddit, where even some language contributors have started having doubts about that complexity. One of them was trapped in his own programming language theory ivory tower, the other was trying to convince them that they are losing developers if they keep adding stuff to the language.
That discussion was a clear hint that the Rust developers don't have C and C++ programmers in mind when designing Rust. They have their own ideas about how a modern systems programming language should look like, and they're doing that. Perfectly fine, but we need to correct the misconception that C or C++ programmers will rush en masse to learn Rust.
Rust can prevent all data races but not all (any?) race conditions. Related question: can you use the type system to catch a subset of race conditions?
https://stackoverflow.com/questions/49023664/could-software-...
>I have a very hard time grasping all the functionality/concepts
is (partially) because this
> if we ever want to control the tsunami of security flaws
Most focus in how the borrow checker work "against" you but that is not even the harder. Performance and how manage memory are more "painfull" in rust.
BECAUSE NOBODY KNOW HOW DO FAST & SAFE CODE.
Not ALL the time. Without extra help of the compiler your assumptions can get wrong in invisible ways...
Rust WANNA:
- See what is costly
- See what is unsafe or not
- See what own what
- See what is on heap or stack
The borrow checker is just a part of it.
From https://this-week-in-rust.org/blog/2019/07/02/this-week-in-r...
Python and Go pick up your trash for you.
C lets you litter everywhere, but throws a fit when it steps on your banana peel.
Rust slaps you and demands that you clean up after yourself.
– Nicholas Hahn> C lets you litter everywhere, but throws a fit when it steps on your banana peel.
> Rust slaps you and demands that you clean up after yourself.
> – Nicholas Hahn
This is brilliant and will save me time explaining language differences. Thanks for sharing.
You need to give it a lot of time. Some of the ideas are really not familiar. I don't think Rust presents some of the ideas perfectly, but I can imagine that in 20 years there might be a whole slew of languages that borrowed ideas from rust and maybe make them appear more idiomatic.
Rust itself borrows a lot from functional programming while also topping the story with lesser-known things like lifetimes, so no wonder it feels alien to a lot of people. In fact, the following:
> I can imagine that in 20 years there might be a whole slew of languages that borrowed ideas from rust
is actually already happening, except it's FP that's inspiring contemporary language designers (including Rust team).
To me personally even limited familiarity with Haskell probably helped a lot back when I started tinkering with Rust, it all felt more familiar to me than to average C or Python dev.
They will be almost at home with Rust.
The biggest hurdle is dealing with the borrow checker when writing GUI code (hello Rc<RefCell<T>>), but for other kind of applications it is quite ok.
Also it speaks a lot that Ada, C++, Swift are adopting the same ideas regarding the borrow checker, even if implementation has some constraints given backwards compatibility.
On the contrary, Rust allow us (non C++ programmers) to use a system language without fear of breaking something. I'm a Rust developer with Ruby background and loving the language more and more.
The biggest problem with Rust right now is actually its novelty and lack of maturity, that makes using it at this time a lot more problematic than it should be. But Java and Python were once "new and unproven" languages, too.
Usually the performance folks that get scared are the ones that put all of them into the same basket.
Rust has accumulated its complexity over four years, and it's already comparable to C++. The thing that worries me the most about Rust, is how the language will look like in another 10 years.
I don't find anything about the language to be particularly more complex than, say, Python or C++.
If your program is running on the server reading from a DB and producing simple JSON (like I assume most of HN's audience), rust is probably not what you want. There's plenty of more pragmatic approaches. At least I think it's not the right language for my employer's department (and it pains me to say that)
If what you want is to write code that runs on bare metal then consider Rust
The closest I was to bare metal, i.e. code that works without an OS, when I developed stuff for “small” MCUs, like Intel MCS51, Motorola COP8. Rust supports none of them: https://forge.rust-lang.org/platform-support.html
I’ve developed for Nintendo Wii, nominally there’s an OS but it’s very “thin” one, mostly statically linked libraries provided by Nintendo. Rust can’t compile for that platform either, it only supports PowerPC Linux.
I’m currently working on low-level software working on bare Linux kernel. Rust apparently supports ARM Linux, but C libraries are literally everywhere, both kernel APIs and user mode: drm, kms, gles, udev, freetype, low-level kernel stuff like tons of ioctl calls for SPI and USB I/O, wpa_supplicant, and more. That’s too much native C stuff to integrate together, using a foreign language causes too much friction.
I can think of bare metal software for which Rust is good. If I would work on x86 bare metal hypervisor, I would look at Rust very closely. Platform support is good, not much libraries are needed, and the project is extremely security sensitive so using Rust will probably pay off in the long run. But I don’t think that’s a rule, looks like an exception to me.
There are some middle ground options though, like Zig, which is a nice simple C like language with less undefined behavior and no nulls. so safer, but not offering memory safety.
For example, Rust puts &T and &mut T at the forefront, which leads to a slightly alien way of handling aliasing- it's all or nothing. This makes some things feel way harder than they are in C, but helps out the optimizer (every pointer is now restrict/noalias).
A different language could emphasize (the equivalent of) &Cell<T>, which allows shared mutability but restricts certain "shape changing" mutations. Most of those C patterns would feel easy again, with a bit less of Rust's non-safety-essential guarantees.
[1] https://ferrous-systems.com/blog/rust-analyzer-status-openco...
HTTP stuff benefits a lot from asynchronicity, and so there’s been a lot of churn over the past few years as this story shakes out. We’re almost there though!
Have a look at the sort of things you can do with it https://github.com/actix/examples
Haven’t used it extensively, but it’s pretty feature-rich and looks reasonably well-maintained.
Beware though to use an executor that can drive the new futures and watch out certain libraries using `tokio::spawn` , which will cause panics.
Some executors for the new futures:
https://docs.rs/futures-preview/0.3.0-alpha.17/futures/execu...
https://github.com/withoutboats/juliex
And a web server to try out async/await on nightly:
https://github.com/rustasync/tide
Compatibility layer from 0.1 to 0.3 and back is in futures-util-preview if compiled with the feature flag `compat`.
https://docs.rs/futures-util-preview/0.3.0-alpha.17/futures_...
It's based mostly on this article, which predates std::future: https://www.viget.com/articles/understanding-futures-in-rust...
care to expand on that?
This is hopefully solved by the Runtime crate and the crates using it will use a more generic version.
If this is for fun / education then learn Rust. It's conceptually nicer and doesn't have legacy cruft from decades of industrial use.
The first component is conventions and idioms for managing allocations, and Rust will force you into (and support) some good (but nontrivial) ones.
The second component is self-discipline. Look at the long history of vulnerabilities in C and C++ code that are due to carelessness -- of an oops that a programmer made when they knew better.
If what's being considered is Rust as a stepping stone to C++, how much does Rust help with the first component, and is Rust even counterproductive for the second component?
Regarding counterproductive for the second component, you might've seen a conventional practice of grinding the Rust Clippy until the code compiles. I don't know how that affects the development of self-discipline (e.g., maybe some people try to make a practice of being Clippy-free on every compile attempt?), but it seems a reasonable and interesting question to ask.
(I'm not dissing Rust for this. I mostly like Rust, and would be happy to be working in/on it.)
There are of course, fairly significant differences in idioms, and things like that, but that’s true for every language switch.
So you have a standard trait from the language officially, that is useless without a third party library?
The reason they’re external is, depending on what you want to do, you’ll want an executor with different characteristics. An embedded executor has very different needs than a network IO executor than a GUI event loop. By stabilizing the trait, we can ensure library compatibility: everyone agrees on the same interface.
Given that we’ve invested so much in making it easy to add libraries to your project, including a single one wouldn’t be appropriate.
Are there talks to make that a reality in the next 18 months?
Is `async / .await` going to be just syntactic sugar around `Future` or is it going to necessitate an executor lives in the standard library?
Note as well that Tokio isn't the only library that can be used here, there's plenty of experimentation in this space.
I wish the stigma against "unsafe" C++ was a bit more rational. People who use it aren't the kind fresh out of bootcamps and mostly realise the gains and risks. But maybe I'm skewed by my job which uses C++ and takes any risks seriously.
In comparison to array-based lists they're: - less memory-efficient, - do not allow random-access, - worse for cache locality (so can be up to orders of magnitude slower) and - more complex.
They are nice to learn some principles in the context of an Intro to FP course but apart from that, meh.
Almost any kind of data structure in Rust is extremely painful to do efficiently. You either go the unsafe route of you drowned in a sea of boxes and cells.
On Reddit recently somebody gave the ludicrous claim that you shouldn't have to write your own data structures in rust - the rust system library should have everything you need.
https://www.jetbrains.com/lp/devecosystem-2019/cpp/
34% don't use any kind of unit testing.
35% don't use any kind of static analysis tooling.
36% don't use any kind of guidelines.
Having proper metaprogramming is also really great. Sure, you can definitely go overboard, but a few things are just only possible with proper metaprogramming like quickly printing the value of a struct or enum for debugging and easy serialization/deseralization (like serde does). It's just a huge boon for doing introspection.
But it's not just the particular features that are important, it's the fact that best practices are integrated into the language. There are standard solutions for most things: error handling, unit tests, build system, package management, formatting style, etc. Sure, if you have a long-running C++ project, you're gonna have answers for all that, but the consistency matters when you want to integrate libraries.
I think if you're going to use Rust, you should try to speak to its strengths rather than retrofitting existing C++ idioms onto it. There are both real advantages and very real costs to doing this, and you certainly shouldn't just switch an existing C++ codebase to rust.
If such a strategy stands between you and understanding, I'd suggest you to use silence gaps of different lengths. Like 0.5s for space and 0.2s for ::.
The wording here confuses me. They say they took the implementation from hashbrown, but then finish by saying that the implementation is different. What am I missing?
Hasher => Takes the key and turns it into a hash (in this case a 64bit hash).
HashMap => Takes (key, value) pairs + a hasher and then does "magic" to get a fast lookup based on key+hasher.
The "magic" part is what changes. (which include thinks like which datastructures are used to store keys/values, how deletion is handled, how hash collisions are handled, how the given hash is used to lookup keys, etc.).
I'm still looking forward to const generics and a more usable const fn. In a way it's a shame Rust doesn't have a purely constant function in the interim. But a hybrid function will be more versatile once it allows some form of looping.
The last thing on my wishlist is extern types (aka opaque types aka void *). The current workaround using a pointer to a [i8; 0] type relies on LLVM's particular handling of such pointers and always looks weird in rust.
It's how I interface with C and C++ callback functions.
[0] https://doc.rust-lang.org/nomicon/ffi.html#representing-opaq...
I'd love to blog on this at some point but I think that the real big win here was being able to use ? to early exit in async code.
I'm excited to see what the future brings here - we're still pretty new with async/await and building our own internal patterns.
Also very happy to not being forced to write .map_err ever again.
When we get some spare bandwidth we'll definitely see if we can get some extra productivity out of using &self. So much of our existing futures code is either self-less or uses some macro code to generate glue to allow us to use Arc-typed self - this is to allow a bunch of async core code to interop with these async platform drivers.
Been on a crash course getting better at architecting Rust programs for nine months. Luckily the Rust ecosystem and toolchain is getting even more amazing each time around so we can justify some work to refactor and try new approaches.
https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html#the-a...
I would love to see how such libraries are built from scratch in a low level language. I feel like I would learn a lot as well.