Hacker News new | past | comments | ask | show | jobs | submit login

> First lesson: Rust isn’t as hard as I expected

We're going to see a lot more of this. As the language has matured, the Rust folks have paid great attention to easing the learning curve. Even with the borrow checker, it's not that far from Java or a scripting language these days. Most people won't hit lifetimes early on in their use.




> Most people won't hit lifetimes early on in their use.

Depends on what you're doing, doesn't it? If you're using Rust for its original design-goal purpose—as a systems language—then you're probably writing some kind of daemon that keeps persistent in-memory state between RPC requests from clients; or some kind of UNIX-ish CLI tool that reduces over IO streams. And as soon as a request, or a stream event, wants to persist some state into a longer-lived scope, lifetimes rear their head.


A junior programmer isn't going to encounter this unless they're trying really hard.

Someone with the knowledge of how to write code like this is already familiar with the problem domain and the vocabulary. They'll know enough to be able to find out how to get this performance out of Rust.

New programmers aren't going to look for this or need it right off the bat. They'll still be able to leverage a modern, safe language with lots of features and an extremely compelling package manager.


Or on a more basic level - trying to store a ref in a struct. There's plenty of ways to not do that or think about the problem in other ways, but I think it's fairly easy to accidentally run into that problem early on.


I don't know. I recently took a Rust course and our day three project was to build a simple multi-threaded webserver. The really easy kind in C where you accept a connection and then spawn a thread to handle the request so the main thread can get back to accepting new connections ASAP.

This turned out to be quite challenging in Rust, even when starting from a working single threaded server. Threading the needle on borrows was quite a challenge.


Interestingly, a multi-threaded web server is the final chapter of "The Rust Programming Language" (full code is at the end of https://doc.rust-lang.org/stable/book/ch20-03-graceful-shutd... )

It ends up being pretty short, though we also build a threadpool by hand. If you used a package, it'd be even smaller. (I like scoped_threadpool myself) (And the FnBox stuff will go away once I write an update for it, it's no longer needed.)

It does the same: grab a connection, spawn the thread. There's virtually no borrowing.


Having used Rust for several months, I'd say that multithreading is still one of the biggest pain points (strangely, as it's also one of their headline features). The only thing I've encountered so far that's harder is pointer-juggling data structures, but at least in that case you can mostly just use the (excellent) ones in the standard library.

The "crossbeam" library helps a lot: https://docs.rs/crossbeam/0.7.2/crossbeam/ It's the only way I know of to have thread closures with a less-than-static lifetime, which helps a ton with borrowing/moving and also general encapsulation: https://docs.rs/crossbeam/0.7.2/crossbeam/fn.scope.html.

Once you get the hang of it you can move forward pretty well, but the ergonomics around Rust concurrency, especially in the standard library, really need some work if they're going to continue focusing on it in their marketing materials.


Did you learn C (or any other programming language) by writing a multi-threaded web server in it ?

The Rust book actually ends by showing you how to do that, but... there are many reasons why that's the last chapter in the book. Starting there is definitely not the most efficient way of learning Rust.


I did for golang. Assuming you know how to program in general it's a very basic task.


Ehh... it's a basic task as long as you never touch shared mutable state. As soon as you have to do that, you need to work out what the abstraction for dealing with shared mutable state in your language of choice is.


I mean most languages you don't. You lock do some stuff then unlock. Rust prevents a whole lot of bugs by not making it this simple but that means if you pick anything with threading as a task to jump into the language your going to have a much harder time.


Rust `Mutex`es are simpler to use than C++ ones.. so if you just `Mutex` your shared state away, writing an app on top of `actix-web` or `hyper` or `tokio` is dead easy once you learn how to use the framework, particularly if you have already done that before in Go.


Did you just use Go, or did you write your own Go implementation including its goroutines run-time and then write a web-server on top?

Because if you did just use Go, in Rust you can just `cargo add actix-web` (or `tokio`, `hyper`, `async_std`, or any other goroutine-like run-time) and write a multi-threaded web-server in approx. one line of code.

What the Rust book example shows is how to implement what the Go language uses inside its run-time for running goroutines, which is a much harder thing to do, and very different, even though that's something that every good web-server uses somewhere in its stack.

Learning Rust by using `actix-web` to build a simple web-server is ok, but learning Rust (or any other programming language, really) by implementing `actix-web`, is not a very efficient way of learning the language.


I had the same initial reaction. I wanted a tokio UDP server that delegated to other things. Working w/ tokio streams, futures, async (which I understand are all still in beta) was quite challenging to make sure they could all get back to the read/write of the UDP socket. Basically I end up having to split UDP read/write then concat/join disparate streams or use mcsp channels to fan everything out and get it back to a single stream.


Personally I think languages with tracing GC are much more productive for those kind of scenarios.


It depends on what you're doing. If you're writing sorting algorithms, it's not far from Java (C++, really, but). If you're writing something multi-threaded, or asynchronous, or with polymorphism, it's very different. If you're writing data structures that involve pointer-juggling, it's extremely different unless you bail out and use unsafe!{}.


I checked out rust around 5 or 6 years ago, and it was a mess of sigils for the borrow checker. Things have improved significantly since then. If you haven't checked it out in a while, it may be worth another look.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: