Live data from Hacker News

Rust Is Hard, Or: The Misery of Mainstream Programming

hirrolot.github.io

131–140 of 811 posts

Re: Rust Is Hard, Or: The Misery of Mainstream Programming

#131

Unpopular opinion: I find rust code unreadable. And I consider myself a polyglot. I am sure all those symbols have a special meaning but it's like perl to me. Just throw some random special characters and they all mean something.

You are not the only one. I find rust code unreadable too even though I can understand it. I wish the type signatures and function definitions were on separate lines a la Haskell. That would have drastically improved the legibility.

You can do that in Rust by using a "where" clause. Put in a letter for each type, then define them on different lines.

Re: Rust Is Hard, Or: The Misery of Mainstream Programming

#132

Earlier quoted context omitted.

You are not the only one. I find rust code unreadable too even though I can understand it. I wish the type signatures and function definitions were on separate lines a la Haskell. That would have drastically improved the legibility.

You can do that in Rust by using a "where" clause. Put in a letter for each type, then define them on different lines.

Anything with trait bounds beyond `fn foo(t: T)` should put them in the `where` clause (and in this case, it arguably should be `fn foo(t: impl Trait)`).

Re: Rust Is Hard, Or: The Misery of Mainstream Programming

#133

Earlier quoted context omitted.

This sounds like a terrible way to exist.

Happy way to exist!

I suppose ignorance is bliss after all - I mainly hope you are exaggerating when you say 'fumbling through'.

Re: Rust Is Hard, Or: The Misery of Mainstream Programming

#135
post #92
post #60

Earlier quoted context omitted.

> Most of the pain here come from the unholy trifactor: combining async, lifetimes and dynamic dispatch with trait object closures; which is indeed very awkward in practice. Even in regular Rust, trying to get too clever with lifetimes can cause serious pain. The usual culprit is complex code that tries to never allocate memory. "Oh, well this closure borrows this parameter from the parent function, and then stores a…

> If you have a long-running async function, then pass parameters by value! If you have a polymorphic async function, then return your result in a Box. I've taken to making heavy use of the smallvec and smartstring crates for this. Most lists and strings are small in practice. Using smallvec / smartstring lets you keep most clone() calls allocation-free. This in turn lets you use owned objects, which are easier to re…

However the constant checking if something is on the stack or heap is a big performance problem for smallvec. It results in terrible cpu branch prediction.

Re: Rust Is Hard, Or: The Misery of Mainstream Programming

#136
post #93
post #79

Earlier quoted context omitted.

Re: fearless concurrency... Would Rust prevent you in general from writing code that could deadlock, btw? Thread1: takes lock A, ..., tries to take lock B Thread2: takes lock B, ..., tries to take lock A Looks like you should be able to pass Mutex and Mutex to both threads otherwise what's the point of mutex if there's no way to share data protected by it, so it doesn't look like it prevents you from hitting this sce…

Rust doesn't protect you against deadlock. I wonder if it is similar to the halting problem. Can deadlocks even be prevented in theory?

In the general case you're right, it's equivalent to the halting problem. The outline of the proof by reduction: set up two communicating processes in a way that will deadlock iff a particular loop in one process fails to terminate. So if you had a deadlock detector for arbitrary communicating processes, you could use turn it into a termination detector for arbitrary loops.

Re: Rust Is Hard, Or: The Misery of Mainstream Programming

#137

Earlier quoted context omitted.

Rust isn't hard for the things you try to solve in Rust. The author compares Rust code with Go code. Those two languages serve entirely different purposes, with entirely different mechanisms behind it. Go does what the author does with ease because the runtime fixes all the complicated parts for you. You tell Go what you want and it'll try to solve all the memory management/threading/memory safety issues for you, usu…

> I think the difficulty in Rust lies in that it will enforce correctness. Competing languages are less strict about that, especially when it comes to threading. Enforcing correctness at compile time is not the only way to insure correctness. Some do enjoy solving language puzzles (so choose Rust) and some prefer thinking before coding and prefer solving design puzzles. I personally prefer that latter, as the 'hard'…

This is the "don't do anything wrong" model of software development, and while it works well for some, we have enough experience as an industry to know it doesn't scale.

Crucially, it's hard to prove whether or not you've actually solved whatever design issue you wanted to overcome. Such a proof usually would entail some sort of analysis of the program as written (because it may actually differ from your design). To perform this analysis, you may want to annotate the lifetimes of the various objects as they are declared, so that you can track (for example) that some memory is not accessed after it is freed, or any other number of issues.

This lifetime analysis as you would imagine can be very tedious and complicated, so you would perhaps want to automate the process. And that's essentially why Rust's borrow checker exists. It's almost inevitable that it should exist imo. Seems completely obvious after the fact.

Re: Rust Is Hard, Or: The Misery of Mainstream Programming

#138
post #10

I wish there was a Rust-like programming language that was just a little bit higher level than Rust. I like Rust's wide ecosystem with high quality packages, the nice type system, traits, the idea that my code generally runs pretty fast even if I'm being lazy about writing good code, and my code usually working correctly if it compiles. I care about speed and correctness but Rust makes me also care about ownership an…

People don't like to mention C# since like PHP, it has a bad rep from early days, but C# 10 and .NET 6 hit all the sweet spots people are mentioning. C# and .NET now run on Linux and Mac and compile to a single executable like Go with tree shaking so the binary is much reduced. I don't really care, but it's a shame people don't take another look at C#. When I learned Rust I was surprised how similar it felt to C#, but much more ergonomic.

Re: Rust Is Hard, Or: The Misery of Mainstream Programming

#139

Earlier quoted context omitted.

I agree, I don't understand why so many people lately seem to want to use Rust for web domain stuff. I don't like Go, I hated the year I had to work in it @ Google. But frankly, it's better suited for 'server' type stuff, unless you're talking about a very specific type of server that has super intense latency guarantees. And now that Go has generics, I'd probably hate it less. Go is the new Java. Rust is the new C++…

Why? Because it's stupid fast, fast means serving an order of magnitude or more clients before requiring scale up. Scale up means $. No stop the world GC time situations, etc. That's basically it. To be fair, I usually prefer to use go as well, lately though rust is more appealing.

The problem is there is more than one kind of "fast". There is latency "fast" and throughput "fast".

For a lot of web stuff you need throughput more than you need latency "fast".

In order to do throughput well you need concurrency.

Re: Rust Is Hard, Or: The Misery of Mainstream Programming

#140

Rust does not have to be this hard. Most of the pain here come from the unholy trifactor: combining async, lifetimes and dynamic dispatch with trait object closures; which is indeed very awkward in practice. Async support is incredibly half-baked. It was released as an MVP, but that MVP has not improved notably in almost three years. There are lots of ideas, some progress on the fundamental language features required…

Rust is like C++ in the following way: it has many features and a complex type system, but that doesn't mean you should use all its features all the time!

Dancing around with lifetimes can be premature optimization. Yes you can write very efficient code that way but if you find yourself spending tons of time fighting the borrow checker you might be overdoing it.

I tend to use Arc a lot in async code. It makes things relatively straightforward and easy to reason about. Mixing lifetimes with async is probably the most confusing thing you can possibly do.

Post reply on HN