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

Is rusts most loved status simply Stockholm syndrome? I've really tried with rust, and we simply don't get on. I hear all the arguments about CVEs and wonder if rust will reduce the number of these problems simply by disabling the programmers that create them. I understand the draw, I want to love it, but i think I might not be smart enough.



No, it's a selection effect. The stackoverflow most loved metric is

    people_who_want_to_keep_using_the_language / people_who_have_used_it_in_the_past_year

Since Rust is so early in its adoption and there are few jobs, many of the responders are hobbyists who are into Rust, like it and want to keep using; not necessarily people who use it for work. And since you only take into account the people who have used it in the past year, you ignore all the people who have tried Rust before that and didn't like it.

As an extreme example, let's say I created a language in 2020, the entire software community tried it and they absolutely hated it and unanimously rejected it as the worst language ever but it still has 2 users (my mom and I) who want to keep using it - that languages would score 100% Most Loved on stackoverflow's survey even though it was hated by the overwhelming majority of people who tried it.

With this formulation you create the strange effect that if people hate a language enough to stop using it, the language's most loved metric goes up after a year.


This selection effect cannot explain Rust's standing relative to other new languages and neither can it explain why Rust's popularity (as measured by "most loved") increases over time as more and more companies are using it. Here's the history of Rust's "most loved" percentage going back to 2015

  Year - Most Loved Pct. - Rank
  2015 - 73.8%           - 3
  2016 - 79.1%           - 1
  2017 - 73.1%           - 1  
  2018 - 78.9%           - 1
  2019 - 83.5%           - 1
  2020 - 86.1%           - 1
  2021 - 86.98%          - 1


I think that's consistent with my line of thinking - if in 2015 some people tried it and decided that it's not for them, they drop off from the sample and % loved goes up in following years.

Not claiming that this explains the entire increase in the percentage (I have no way of knowing) but I don't think this data contradicts my reasoning either.


In order for this line of thinking to explain the statistics, either (1) Rust would have had no users over the time period or (2) more than the loved percentage of new users like the language (mean goes up).

It's pretty trivial to see that Rust adoption is increasing, so you can discount (1).


How is it different than in case of every other language? Also, why not another newer language tops the list?


Clojure is the second most loved in 2021, and it isn't like every company is rushing out to adopt it.


Rust is really hard. So while people that don’t like Javascript still continue to use it, but people that don’t like Rust are likely to drop it like a brick.


Rust is too painful for hobby projects, IMO. Over the years, I've worked in C, C++, Go, Perl, Python, PHP, Java, Scala, JS, Tcl, ... others I've forgotten, most professionally and well as for personal projects.


I've used Rust for a hobby project, it was more painful before, but they have fixed a lot of the churn issues. The ecosystem is more or less stable right now, compared to before


Matter of taste.

I find Rust perfect for hobby projects because:

1. Squashing bugs that show up after the code successfully compiles (or, in Python's case, appears to work) is a big drain on motivation.

2. The ecosystem's focus on API stability means that, once it works the way I want, the costs of ensuring "it built/ran yesterday, so it should build/run today too" will be minimized.

3. I don't have to write as many unit tests to feel I can trust it with my data.

TL;DR: Once you're on the same wavelength as the compiler, Rust is great for projects where your motivation is purely intrinsic.

(Well, that and the compiler has been constantly improving. Things especially got much better after non-lexical lifetimes landed.)


I'm a bit surprised that Rust is really the top language here. I would have expected the top ranked languages to be nowadays-relatively-unpopular languages with dedicated long-time users, like Lisp, Tcl, Perl, and APL.

Is this weighted somehow by overall popularity?


Well the second one is a LISP (Clojure), which isn't really popular (relative to more mainstream languages).


There's probably an additional layer of substantial selection bias here. But maybe that explains the effect in the first place, greybeard Tcl users possibly didn't bother to take the survey while Clojure and Rust evangelists did.


This comment right here.

For most people who program for a living, the hype over Rust means little. They need to use what is in the industry right now. Often, that is a tried and true language that is relatively easy to learn and use.

Having a complex programming language which limits you and controls how you use it does not sound appealing to those who need a feature done, fast.


> Having a complex programming language which limits you and controls how you use it does not sound appealing to those who need a feature done, fast.

This is so interesting to me. I'm a Rust programmer by trade (as in - I'm not a hobbyist, I actually write Rust for work). We've found that, while the feature work is a bit slower in Rust than in other languages the company used to use (mostly Python), they tend to require a lot less maintenance down the line (less bugs, easier refactoring), and so it ends up canceling out a bit.

I also never find that Rust limits or controls me in my day to day work. There are some things you cannot do easily, sure, but those things tend to not matter in application code. Linked lists are hard, graphs are hard, but when writing an app, I just use an existing dependency like petgraph or std::collections::LinkedList instead of reimplementing those datastructures. And if you need to write those things, it's not like it's impossible, you just need to drop down to unsafe rust, and ideally figure out some safe way to expose that API.

Really, the biggest disadvantage of Rust is that its learning curve makes onboarding newcomers much harder if they don't have experience in the language. For Python/Go/JS/Ruby you don't really have this problem, even if a potential recruit doesn't have experience in the language, they will probably be able to pick it up as they go without too much trouble. But in Rust, it can take a fairly significant amount of time to get up to speed and stop fighting the compiler, in the order of several months.


This feels like a common pattern. Languages like Rust and Go seem to pick up a lot of users from the world of dynamic languages, who then incorrectly associate the productivity gains of static typing with the specific language they picked.

A lot of programs written in Rust would almost certainly be better off being written in Kotlin. The one in the article is a good example. Why are they writing a messenger bot in Rust? That doesn't seem like the sort of use case Rust was targeted at. It's also a modern language with a lightweight syntax and pretty good static typing, great refactoring tools etc, but it's way more user friendly. There's no borrow checker because it's GCd, compile times are much faster (at least for the JVM version) etc.

You can also use Kotlin/Native or GraalVM native-image to produce standalone executables that don't need a full JVM, if that's a requirement for your use cases. The native images are astounding. They can start faster than programs written in C and their memory usage is also way less than a typical JVM app. Downside is of course compilation time but you can avoid that by just developing on the normal JVM and then AOT compiling at the end when it's time to release.


> Why are they writing a messenger bot in Rust?

AFAICT Rust is a general purpose programming language. People can use it how they want. How do you learn a recent programming language? "hey boss I'm going to write production code in a new language that I haven't learned. Lol YOLO"


The funny thing about this is, using rust for production is way safer than an old language like C or even C++. So the YOLO part isn't crazy here. If you don't use unsafe you cannot, read can not, get data races, among a host of other common bugs.

Now if we were talking about some other "new languages" not naming names, you can memory leak kilobytes writing hello world... Yikes.


Well, the dispatcher problem is applicable outside of messenger bots too. But your point is right. I think it was a mistake that teloxide is written in Rust. I just wanted to learn a new language so I was like, why not writing such a library in Rust. Don't make my mistakes.


> We've found that, while the feature work is a bit slower in Rust than in other languages the company used to use (mostly Python), they tend to require a lot less maintenance down the line (less bugs, easier refactoring), and so it ends up canceling out a bit.

Python to Rust is a pretty radical swing from one approach to language design to another. I'd expect you could solve most of the maintenance problems with Python by switching to something statically typed but with garbage collection (e.g., C#, Java, or go), without incurring the costs of moving to Rust.


Well, we have other reasons to chose rust rather than a GC'd language (mostly has to do a lot of FFI, which Rust makes much easier than go or Java). I do agree that, if GC'd language fits the problem space, they tend to be much better.


GC has little to do with FFI though. In C# P/Invoke, you basically just declare a static method as external and specify the library where it lives, and that's that. So far as I know, Java has a similar story these days, no need to write JNI wrappers by hand etc. Go is special not because of GC, but because of its green threads.


GC and FFI do have a lot to do w/ each-other though, because FFI usually introduces unmanaged objects.

When a lot of what you're doing is interacting with low-level platform APIs, you end up having a lot of those unmanaged objects. After a certain point, the upsides of using a GC kind of disappear because you still have a lot of places you have to worry about those objects.

Of course, this can be worked around by providing managed wrappers around those unmanaged object, but at a certain point, it becomes easier to just drop down to an unmanaged but safe language (like Rust) that model the unmanaged resources more accurately. In my experience, it's somewhat easier to provide Safe Rust wrappers around your average Windows API than it is to provide a C# Managed Wrapper around the same.

---

And yes, go is special because it has very smol stacks, so doing any kind of FFI on it is a bad idea.


Unless your code is strictly glue between those lower-level APIs, GC is still a benefit for the majority of it. And, on the other hand, the lack of it in FFI is, at worst, similar to C... except you still have all the other language features (like, say, null safety or pattern matching) at your disposal.

I'm genuinely curious as to what would make FFI in Rust easier than in C#, assuming an apples-to-apples comparison (i.e. use of "unsafe" and associated features in both cases"). Most complexity in P/Invoke shows up when you try to use it to automatically map data to managed data types; but in modern C#, you might as well just use raw pointers, stackalloc, spans etc.


Rust seems to excel in having an ecosystem that provides binding helper libraries like PyO3, Neon and napi-rs, Helix, etc. which both ensure "if it compiles, you're doing the C glue properly" and provide a layer for automatic type conversion.

...so requiring `use of "unsafe"` is often akin to forbidding Cargo/pip/NPM/etc. and then calling the language un-productive or faulting a procedural/imperative language for performing badly when you code as if you're writing Haskell.

https://www.hobofan.com/rust-interop/

https://areweextendingyet.github.io/

Using the ecosystem rather than reinventing it is a core tenet of Rust's value proposition.



I’m still learning Rust, but the idea of having to use unsafe features to implement something as simple as a linked list seems “wrong” to me. What am I missing?


I kind of hit a wall with Rust after realizing that something like doubly linked lists are difficult because when two nodes are referring to a node between them, you don't have a clear owner. So basically all situations where you have two or more references to an object need to be thought out carefully, and for me it was a bit of a let down (even though I fully understand the reasoning behind it and why it's useful). For now I stick with languages with GC.


So here's a weird thought, why should you ever write your own doubly linked list? Why shouldn't you use one that a community of people has vetted and juiced for performance instead? In C what I just said is for some reason heresy.

But yes you are right, anytime you have two or more accesses to a data structure you do have to think a little harder about it. Usually you just want to use a reference to that object, sometimes it makes sense to clone it, sometimes you want to pass it by value and return it by value. In the case of doubly linked lists you probably want to drop into unsafe code.

I get it though, GC languages are more zen in that regard.


Writing your own data structures allows you to write it to suit the specific needs/constraints of your problem/domain. Typically that means you get something that is significantly simpler, faster and with a different feature set.

Libraries are typically optimized for generic use, so are often more complex, slow, and difficult to extend with new features (both coding wise or the features might not be suitable / have trade offs for other people).


Won't let me reply to fizzynut, but this is a reply to you.

Yes making data structures is important, and the reality of that is, there are people in the ecosystem creating fancy ones which can be leveraged for your use case.

If that doesn't exist then yea you have to write them. Sometimes that's difficult(you need to use unsafe), sometimes it's easyish and you can use all safe(I did this for a graph type). It can be done(lots of people are doing it), but I think what it shows is, data structures can be difficult to do correctly.

In a worst case scenario you could write it in asm inside rust if you really need a low level control, or write it in C/unsafe rust and ffi or just write it in.

Basically worst case scenario in rust is writing something closer to C.


Lots of people writing their own data structures and libraries should be a reflection of the different needs and diversity of the ecosystem, but if it's a reflection of difficulty then it tends to lead to a much narrower ecosystem.

That isn't to say a narrow ecosystem is necessarily bad, it can often be good if a particular language is used for a specific domain as all the libraries and data structures will likely be a better fit for your problems. Going outside of those constraints can often be very punishing in those languages though.


The fact is that writing a doubly linked list correctly is hard and it's easy even for veterans to miss things. Rust is going to put those invariants in your face.

My advice would be not to judge any language on how easy it is to implement a doubly linked list. 99% of code you write will likely not be that, and that particular data structure exposes a lot of choices and trade offs at a time when youd be better served learning other parts of the language.


Unpopular opinion but the whole memory safe idea is more niche than HN commenters would have us believe. Most of us are writing web apps and services that do not have strict memory requirements nor catastrophic failure modes.

Dynamic languages and GC'd languages cover most of what our employers are paying us for: web apps, backend services. It is ironic to build super safe software, then deploying them on kubernetes, written in a GC'd language prone to nil dereference errors.

Rust has its place, but it's a very small place. These days computers are so fast there's companies worth billions built on Ruby and Python, if you go native with a GC language you'll cover 98% of your needs.

Rust IMHO has gone too far towards safety at the expense of developer ergonomics and pragmatism. We're so expensive that adopting a subpar language that is easier to grok is often a savvier business decision.


> Most of us are writing web apps

Indeed. I'm a Rust dev somewhere it actually matters (video dev - we have to process 60 frames a second, for hours/days on end, with completely predictable performance, without crashing once) and I'd never pick it if I just wanted to build a webapp where nothing really matters and if the whole thing falls over we can just put it in a retry loop.

There's plenty of code out there that /cannot/ be written in Ruby/Python/Go/C#. Rust solves some really hard problems for people working on that type of code. But it's not what most people on HN are working on.

I think the problem is that a lot of web developers do not really understand that this type of code exists, and that languages which do not target web development can be exciting.


Your video app is a perfect example of where Rust shines. I'd add embedded development, data-intensive, fault-intolerant systems and game engines are perfect for this language.

But without even going as far as frontend web applications, stuff like backend services, system services, GUI applications, CLI applications, etc., don't actually need all that much memory safety and control over allocations.


Completely agree! When you need to compute numbers or deal with raw bytes, you have C. When you need to be high-level, you have Python, Java, C#, etc. Rust is applicable only in areas where you need both a high-level and systems language. Examples include interpreters, operating systems, browsers, game engines, etc. The hype of Rust just exceeds its problem domain.


This feels a bit like complaining that a tank is badly designed because nobody drives them on the highway...

My understanding is that Rust was designed to be a safe(er) language to write low-level system code than C/C++, not to compete with Python/Ruby/Java for web development applications.


I'm not complaining about Rust. It's a very good language.

I'm complaining about everybody on programming forums, including HN, seeing Rust as the replacement for most, if not all languages. My opinion is that Rust's ideal problem space is much narrower than people think.


Bingo, it's a true systems language. That said, the fact that people can and do write web applications(for practical reasons) with it kind of says something about it's breadth.


The whole point of system languages is that they reach the whole stack.


True, yet what you see around HN and other places are people trying to use it for web development.


Front end or back end? I see nothing wrong with rust on the back end, not sure how it would even work on the front


WebAssembly.


There seems to be a myth that Rust is unusual in being memory safe. All modern GCed languages are memory safe (assuming you don't do anything obviously unsafe like manipulate raw pointers, which some languages might let you do if you really want to).

>It is ironic to build super safe software, then deploying them on kubernetes, written in a GC'd language prone to nil dereference errors.

Nil dereference errors don't demonstrate an absence of memory safety. If the runtime checks for a nil reference before dereferencing and then raises an exception, that's perfectly safe.


I'm not sure if you understand what safe means in this context. One common example is modifying a vector element by reference. If you grab a reference to an item, push something else to the vector, then try to access through that reference, the vector may have re allocated during the push and you're either no longer looking at valid memory because it's been freed, or you're looking at a stale copy of the element.

I don't think the null handling in rust is about memory safety so much as it is their choice in error handling. If you come across a null pointer dereference and your code doesn't handle it, that's a hidden bug. Triggering an exception and handling it is a valid approach, but there are trade-offs. If no code handles the nil exception for example then it's no better than crashing as you would in C. Wrapping things up in try catch can lead to missing recoverable errors or unexpected states. The choice to disallow null is one to avoid common bugs, not one for memory safety, as far as I understand it.


I'm 100% sure that I understand what safe means in this context. All modern GCed languages are memory safe and will not access invalid memory regions unless you use specifically unsafe features.

> One common example is modifying a vector element by reference. If you grab a reference to an item, push something else to the vector, then try to access through that reference, the vector may have re allocated during the push and you're either no longer looking at valid memory because it's been freed, or you're looking at a stale copy of the element.

There aren't that many languages which both use GC and allow you to take references to elements of a vector. Go would be one example. I can assure you that you cannot access undefined memory regions by doing this in Go. (What would happen is that the original allocation backing the vector would be retained in addition to the new allocation.)

>If no code handles the nil exception for example then it's no better than crashing as you would in C

C programs are not guaranteed to crash when a pointer has an invalid value. Dereferencing a NULL pointer will reliably cause a crash if you're running the code on top of a modern general purpose operating system with memory protection, but invalid pointers (which don't necessarily have to be NULL) have the potential to access arbitrary memory regions without raising any kind of error.


> I can assure you that you cannot access undefined memory regions by doing this in Go.

Current implementation of slices and interfaces in Go is not memory safe in presence of data races:

https://blog.stalkr.net/2022/01/universal-go-exploit-using-d...


This is the kind of edge case you can find in lots of languages, including Rust (which has plenty of past and present soundness bugs).


Data races are violations of the memory model; of course any code which produces data races cannot be understood as memory safe?


As far as I remember, some languages like Java are memory safe even if the code produces data races. That means you can't have a reference to a value supposed to be of type A being actually of type B.


That's part of what the Rust borrow checker does for you: tracking who owns what and enforcing single ownership makes data races that much harder to cause.


Turns out I'm the one who forgot what memory safety is o.o I think the part that makes rust's memory safety special is that it also lacks garbage collection


Some people misunderstand unsafe for being anything more than plain memory corruption.

Nope, unsafe isn't a way to do dependent typing in Rust.


The reference to the slot in a vector has to be a kind of object which tracks the vector itself, and an offset into the vector. It can't just be a wrapper for a naked address.


You might be right for the majority, but there are many other large groups who don't have computers that are more than fast enough. There are a lot of interesting and complex problems that can be solved in something like rust that the languages you name cannot be used for. Right now I'm using C++, but rust is of real interest to me (as is ADA, which in some variants lets me prove my code correct)


"It is ironic to build super safe software, then deploying them on kubernetes, written in a GC'd language prone to nil dereference errors."

This is something that escapes a lot of people nowadays.

Everyone uses a browser and they are inherently unsafe.


I feel it is a bit ironic that Apple and Google rather introduce mitigations for C++ in their browser engines than introduce Rust into the codebase.

Meaning that Firefox's gains with Rust will eventually be lost given its market adoption is slowing reaching zero.


Google is investigating Rust as part of a multi-pronged strategy and, while it has the "this is not an official Google project" boilerplate, the `autocxx` crate (a header-parser/code-generator addon for the `cxx` interop crate) is by Google employees.

https://docs.google.com/document/d/e/2PACX-1vRZr-HJcYmf2Y76D...

https://www.chromium.org/Home/chromium-security/memory-safet...

https://github.com/google/autocxx


the thing about Rust's ownership model is that a reference is not ownership, it's 'borrowing', and should be treated as such. But - and here's the kicker - the borrow happens as long as that reference is stored, not just when it's accessed i.e. dereferenced. This makes a number of data structures and patterns difficult and impossible to implement as you can't keep track of references to anything. You can't really make an opaque handle, for example, that can do operations through a stored reference. You have to store some ID or something and then when you want to do operations you need to pass the original container to the function anyway - so what's the point of even having reference types at that point?

IMHO Rust's lifetime analysis should consider borrows only at the point of dereference, not just whenever you encounter an & symbol. They already do that with raw pointers - you can have as many pointers as you want but you only need to mark `unsafe` if you actually dereference one. So at least someone on the team knows how to make that work functionally.


You’re missing that you don’t have to use unsafe, you use a wrapper type which is essentially a smart reference-counted pointer. Rust makes these things explicit.


Because it's a library feature, exactly the thing you should use "unsafe" in, since it should be simple enough to be obviously correct


you're not missing anything.


> And if you need to write those things, it's not like it's impossible, you just need to drop down to unsafe rust, and ideally figure out some safe way to expose that API.

I'm sure you know this already, but for the people reading this: first of all "unsafe" is a very rare, and it's only "less safe" more than fully "unsafe"; ie it's still safer than C++.

And the second thing is that, often you don't have to drop into unsafe Rust, it's possible to achieve most stuff without it, but might incur a small performance cost (idk if some of those can be optimised away by compilers or not).


> Having a complex programming language which limits you and controls how you use it does not sound appealing to those who need a feature done, fast.

This sounds as insane to me as a carpenter who works with power tools saying. "Having safety measures which limits you and controls how you you have to do certain things does not sound appealing to those who need a house build, fast."


I mean, while my understanding of the construction market is rudimentary at best - isn't it actually the case that construction often _does_ end up rushed, or compromised at design level, exactly because of that?

It's not good, and when a bridge falls over the results are a bit more... dramatic and undeniable - but it's not really my impression that other branches of engineering are particularly immune from corner-cutting and deliberate under-estimation.

Edit: though I'll say, just having someone "at random" say they expect better in their industry is an anecdotal evidence that it is at least a bit better. Also, you get to work outside. Truly, grass is greener on the other side of the road.


Or use a GC language with a great typesystem and have both safety and fast efficient development cycles.


That is an option, or if you don't want to deal with a GC because it's eating 70% of your clock cycles under load you can use rust get performance gains and still be writing safe code...


if your GC eats 70% is your clock cycles, your language has a broken GC. in modern Java/C#, GC time is rarely more than 10%


To get to a low GC overhead in Java (and perhaps other languages too) you have to pay with an increase in memory consumption. Sometimes as much as 100% additional RAM to avoid frequent full GC scans.


That's true, but malloc/free based systems also have a relatively high memory overhead due to fragmentation and programmers being worse at inserting frees than the GC. It's not at all clear that the C/C++ model of memory management has lower than 100% overhead for long running programs.


> but malloc/free based systems also have a relatively high memory overhead due to fragmentation

In case you haven't seen it, there's been some interesting progress on that front:

https://www.youtube.com/watch?v=c1UBJbfR-H0


Rust only limits you from writing nonsense code. Seriously that's what the compiler is doing, and that's what people are complaining about. "Why won't this language let me write bad code!". I get it it's hard to learn at first, but, it sounds a little silly to people who have spent the time learning the language...

Believe it or not industry has and is continuing to adopt rust. Microsoft, AWS, government agencys in Europe, the Linux kernel itself (the only other language allowed there is C - think about it). It's really not all hype, people like it because it solves a class of problems from never happening while still performing very well.

I invite you to join the community and learn it. It's a lot of fun once you get proficient with it.


> Rust only limits you from writing nonsense code

This is the ideal, but not always the reality. The Rust borrow checker isn't perfect, so sometimes it rejects code that should work perfectly fine. Hopefully as the language matures (Polonius, GATs, HRTBs…) these cases will become rarer.


Is there a simple example you can point to of rejected code that should work perfectly fine?


A doubly linked list is a classic example. To implement this in Rust you need to use unsafe code.

Come to think of it, an even simpler example is a mutable iterator for a typical data structure. Such iterators usually require 'unsafe' code to implement, even though they are perfectly safe to use. https://stackoverflow.com/questions/63437935/in-rust-how-do-...


Unsafe in rust means you are skirting guarantees given by the language. It doesn't mean the code will blow up when run. It's just an explicit way to tell the compiler you are operating at your own risk. So when you do get UB from using unsafe you look at those places rather then your entire code base...

A lot of people don't seem to realize how easy it is to get UB in other languages. The C spec for example claimed not having a trailing newline at the end of a file was UB...

I also don't think this was an example of code that should compile but doesn't. Rusts' ownership rules make this task hard, but there are lots of people using doubly linked lists in rust... Yes they used unsafe code to do it, and yes it does compile .

The question was show us a case where the borrow checker was wrong.


>Unsafe in rust means you are skirting guarantees given by the language. It doesn't mean the code will blow up when run. It's just an explicit way to tell the compiler you are operating at your own risk.

I'm fully aware of this. That's why I put 'unsafe' in quotes.

However, it's surely fair to point out that you can't implement doubly linked lists or mutable iterators in Rust without giving up Rust's usual guarantee of memory safety. If this guarantee is not actually that big of a deal, as you appear to be suggesting, then why all the hype about it from Rust advocates?

>The question was show us a case where the borrow checker was wrong.

No, that was not the question. OP just asked for 'rejected code that should work perfectly fine'. There are of course loads of examples of such code. Perhaps the simplest is the case of mutable iterators that I mentioned. A correctly implemented mutable iterator is perfectly safe, but rejected by Rust's borrow checker unless certain parts of the implementation are marked unsafe.


It seems you are slightly misunderstanding the point of 'unsafe' as a concept.

And no, memory safety is a huge deal, it is just that the borrow checker cannot verify the soundness of certain code, meaning you have to provide the guarantees normally given to you outside 'unsafe' blocks.

Yes, this means that a few data structures require 'unsafe', but you should be creating safe wrappers around these structures; 'unsafe' won't propagate up your code and poison everything.


> it is just that the borrow checker cannot verify the soundness of certain code

And I was just proving examples of such code for someone who asked. Honestly, some Rust folks get so defensive it makes them very prone to misinterpret simple factual statements about Rust as criticism.

Apparently you don’t disagree with any of the factual statements that I’m making. You just have some vague unsubstantiated feeling that I don’t ‘get’ Rust.


I'm not fighting your claim that the borrow checker has perfectly reasonable situations it can't deal with. That's why 'unsafe' exists. I've already said that.

You're adding other claims and statements that make me question if you actually understand the thing you are criticising.


If you'd say what those claims and statements were, then we could have a conversation. It's not conducive to a good discussion to reply just by saying "you're wrong and you don't get it".


Yes, it has limits. And unsafe let you C++ your way out of it. At least, little code requires unsafe and thar makes it easier to audit.


"I invite you to join the community and learn it. It's a lot of fun once you get proficient with it."

I will if the Rust community agrees on a lighter, less complex language core.

"Microsoft, AWS, government agencys in Europe, the Linux kernel itself (the only other language allowed there is C - think about it)."

Again, they are using only a subset of the language. Linus allowed it in the kernel once devs agreed only to use the Rust core features. They even had to make a new memory allocator, IIRC.


You’re confusing standard library naming. Rust has a layered standard library, “core” and then “std” on top of it. They’re using the core library, because that’s what you do in an OS context. But as far as I know they don’t restrict any language features.

They also didn’t have to write a new allocator; they did extend the interface of the “alloc” library (which sits between core and std) which was then also accepted upstream.


So, what software can you make without relying on "std" library?

I think that a lot of complexity in Rust comes from many different ways to handle memory. You have your Arcs, Boxes, Cells, etc. Then you have a core "alloc" library.

Maybe if everyone agreed on a single reliable method to handle heap memory (since using stack is easy), Rust wouldn't be so hard to use.

The syntax also could be improved. Seeing <Box(T)> or whatever nested three or more levels deep hurts my eyes.


You don't have access to the C standard library in the Linux kernel either, so what is your point? Ime., the core library of Rust is much nicer to work with than the absolute bare bones landscape that is C when compiled with -nostd.

Boxes, cells, arcs, etc. exist for different purposes and if you'd take two hours to actually read about them and their uses, you'd understand why they exist.


You can write lots of stuff. The stuff you lose access too is mostly things that rely on the OS to function, so you lose file system stuff, networking stuff, things like that. Of course, people have written their own implementations of these things when it makes sense to do so.


Thank you Steve. There is so much misinformation surrounding rust it's unreal...

It's also kind of normal to you know tweak a language so it integrates with an OS better... Even if they did change their allocator, who cares?


The problem with rust is its community. A bunch of groupies acting worst than kpop stans on twitter. If you don't make abstraction and write spaghetti code, or if you clone everything, then yeah rust work-ish.


> complex language which limits you

Rust really does not limit you. Anything possible in C or C++ can be done in Rust if you're willing to use unsafe code.


You could also say the same thing about Assembly.


I'm not sure this is true. The aliasing model of unsafe Rust seems much more difficult to write correct code for than these other aliasing models.


Use UnsafeCell if that’s your problem.


This is not the case if you are designing a library. Much of what is routinely used to capture semantics into mainstream C++ libraries is wholly impossible to express in Rust. (C is not even a participant, here.) This is not about template metaprogramming, just ordinary stuff.

Most of that difference is in things that happen at compile time, so this is not a question of Turing completeness.


> Much of what is routinely used to capture semantics into mainstream C++ libraries is wholly impossible to express in Rust. (C is not even a participant, here.) This is not about template metaprogramming, just ordinary stuff.

Do you have any examples?


All above languages are turning complete, so if you can express it in one you can express it in another. The question isn't can you write it, the question is how hard is it to do, and how performant the code will be.

The heart of C++ is destructors: a bit of code that you can write and the compiler will ensure runs when code goes out of scope/is deleted. You can do this in C by remembering to manually call the right code when doing clean up, but it is easy to forget and thus error pron. (I think Rust has this too?)

C++ gives you the ability to do a virtual base class interface, which - as most people know - just means it writes a vtable behind the scene for you. Sometimes people write a vtable by hand in C: it is just a struct of function pointers, but the syntax to do it in C++ is a lot nicer. If you need an interface of some sort the win goes to C++ because the syntax is a lot nicer. (I'm not sure what Rust does about interfaces, I think it has something)

C++ gives you control over copying structs. In C structs are only copied member wise, if the struct has a pointer you need to keep track of both copies so you don't free it early. In C++ you write a copy function that will make a copy of the pointer. You can do this in C by remembering to call the right function when copying a struct, but the default is the wrong thing. (I'm not sure what rust has here, but at the very least the borrow checker will stop you from making a mistake)

C++ gives you move objects - a way to express that a struct is going out of scope, but only after a different one is taking over the contents. This is a variation of the previous, except that you know the original doesn't need valid data anymore and so you just copy pointers and null them in the original. C doesn't have this concept, you can get around it with use of pointers and manual copying of structs in the right places, but the code is ugly. (again, I'm not sure what rust does, if nothing else the borrow checker should allow the compiler to make some optimizations on this lines)

There are a lot more areas where C++ gives you syntax to write correct code that C does not. Rust intentionally doesn't have some of them (class inheritance has been abused often, but I still find it useful enough in a few cases that I think rust is wrong for throwing it out), and in other cases has come up with a better syntax. Overall I don't know enough about Rust to judge it, but I'll take C over C++ anyday.

Note, the above is about the advantages of C++ over C. C++ has a lot of warts that are out of scope for that discussion. I am not claiming C++ is perfect. If you are starting a new project you should seriously consider your language options - including some not mentioned here)


I will note that Rust has all of those features you mentioned. 1) Traits 2) You have to be explicit, by implementing the Clone trait, otherwise arguments are passed by reference or moved. 3) Rust has both RAII and linear typing, which is effectively a proven-correct form of moves - you can't access something that has been moved, unlike C++.

Rust doesn't have class inheritance, no, but often combining traits and delegating to a "parent" field works. Although sometimes that can be considerably more cumbersome, yeah.


I agree that the GP comment does not capture what Rust is unable to express.


You can also see it this way: The philosophy behind C++ is that the existance of a pointer implies ownership. In C, the existance of a pointer only implies liveness (normally; but really the code can decide on its own whether its safe to dereference the pointer).

With the C++ approach I've found myself overthinking the problem many times. But with the insight that pointers are just data, and memory management can be independent, it turns out that programming with raw pointers need not be hard. There is no problem passing a pointer without "move semantics" shenanigans.


You are confused.

There is no sense, in C++, in which a naked pointer implies or suggests ownership. It is the opposite: the continued validity of a pointer value depends on ownership maintained elsewhere. Nowadays libraries keep track of ownership. Most commonly the library delegates that responsibility to Standard std::unique_ptr, for familiarity. Not doing that indicates something different in play.

(It is, in fact, UB even in C to copy the value of a pointer to an object that does not exist anymore. This is the case regardless whether it had pointed to or into a stack or a heap object.)

In C, there is no way to express library ownership of a pointer. So, in C there is always potential for confusion about ownership.


> You are confused.

I give you one advice: Think twice before writing this way again. You are not putting enough effort into understanding what I'm trying to say, and coming across as an arrogant prick.

https://news.ycombinator.com/item?id=31494099

Admittedly, I didn't make my point sufficiently clear, but this isn't even about being right or wrong. (And, once more, I understand what you say. Stop belittling me.)


You must be stuck in C++98 land. In C++11 a pointer always means live (though you may not have rights to store that pointer for later). We use smart pointers to force ownership.


I know. I'm not stuck in C++98 land. I'm talking about how problems are approached in C++ and more generally, OOP land. In large parts of the community, there seems to be this idea that (almost) each little pointer (naked or not isn't my point here) should also be a handle to control the lifetime of the object that it points at.

I'm not saying that it has to be this way, but there is a reason why something like unique_ptr (that can be quite tedious to use in my experience) has become so popular in many projects - IMO it is overused, often leading to more typing work instead of less.

If one is sufficiently used to this way of modelling, it can come as a surprise that memory management needn't be so hard, and doesn't require smart pointers or anything, if the program design (global flow of data etc.) is sufficiently clear.


Thanks, that is a very detailed answer[1].

I'm somewhat confused about why it was downvoted - there is nothing there controversial at all.

[1] In my own toy language, I'm kinda leaning towards objects with destructors. Definitely without the footguns in C++, but destructors nonetheless.


Possibly because it does not mention almost all of the C++ features that Rust still lacks.


> but I'll take C over C++ anyday.

Did you mean the opposite?


opps, yes I did.


What I'm about to write isn't to pick at you - I think it's a systemic issue, and "professional programmers" unfortunately have limited influence on it, at least right now - though I believe "we" could change it - but not while acting as individuals.

> Having a complex programming language which limits you and controls how you use it does not sound appealing to those who need a feature done, fast.

See, I don't think Rust makes that _harder_ - I think it surfaces the real complexity, makes is undeniable. So far in my - by now 20 year old - career, when I've seen most teams faced with complexity that might either slow down a project, or be swept under the rug, the latter was always chosen.

There are _business reasons_ for that, software projects don't live in a vacuum - but those reasons are... _depressing_ at best - by far the biggest one I've seen is that a correctly estimated project would never be approved. Let's just say that figuring that out is a cognitive hazard that can easily increase risk of burning out - literally the sort of knowledge you're better off ignoring.

So ultimately my line of thinking is, Rust's problem in the business sense is basically the same as when you try to code in it: it _tells you that you're trying to sweep something under the carpet_. It tells you that your feature's cost is under-estimated. And to be fair: what can you do about it? The feature wasn't truly estimated by you. It was, almost certainly, estimated by your boss to be "one sprint at most," before he even asked you, and "please estimate this" has an expected answer, and giving any other one has a high social cost. And goddess protect you if your answer might call the entire business model into question.

I don't think any of us can change this, nor that the software engineering workforce is ready to push for changing this. Because even if we convince _our boss_ - the investors will just pick someone else, after all.

--

Anyhow, now you'd be excused in expecting me to advocate some sort of gatekeeping - but no, what I like about Rust is that it attempts to make programming more accessible in a _very different way_ to how many high-level programming languages did. For example:

- it's not _just_ a systems programming language. It doesn't divide programming into "stuff for anyone" and "eldritch monstrosities for the Chosen Ones" - eldritch stuff is just around the corner, in the same language, - it doesn't try to hide the complexity - it tries to give you tools to _explore it_, - and, expanding on the latter, its community values documentation and teaching over restricting use cases.

I don't think Rust is entirely _successful_ at that - but I think that the different model for accessibility is, if anything, more interesting than the borrow checker. I don't think we really need a single language - a garbage collector can be performant and useful, for example, and does it really _have to_ actually result in sweeping complexity under the rug?


IMHO it would be good for Rust to become popular niche/specialist language for systems programming.

Currently Rust is not as complete or well defined as Ada/SPARK or MISRA C/C++ combined with commercial analyzers (Astree for example). At the same time Rust is "too sound and rigorous" for mainstream programmers.

Rust advocates are in the losing battle of of forcing mainstream to adopt "it does not compile unless computer says its ready" style. Reliability and soundness comes with a cost.

Most software is not worth of the cost. When you adopt subscription model, fixing bugs is where the money is. If your app works flawlessly without updates, Apple removes it after few years.


> Rust advocates are in the losing battle of of forcing mainstream

Dunno what you mean. I like Rust. I think it’s by far the best language in its niche, which contains exactly two languages: Rust and C++.

If what you’re doing doesn’t fit into that niche, that’s fine! Don’t use Rust.

Who is forcing anyone to do anything?


I for one as someone who programmed professionally in both Ocaml and Ada still don’t see where Rust is supposed to fit.

If I was doing something high level, I would probably use Ocaml which has nicer features. If I wanted to write safe code, Ada offers a better experience with the availability of SPARK for parts I would probably end up wanting to prove. If I just want to write concurrent code with the certainty I could find someone to maintain it, Go seems the way to go.

Rust seems to want to be a replacement for Ada but seems to actually attract programmers used to high level language chasing the hype.

What’s the story with Rust and verification nowadays?


I think Rust has a good chance to take away market share from Ada and Ocaml. Its eco system (packages, documentation) is more comprehensive already thanks to its broader appeal and being in fashion. I don’t see why stronger verification should not appear at some point. Progress and need is there.


>> What’s the story with Rust and verification nowadays?

It is in progress but likely several years to go before a MVP is released. Ferrocene [1] is the primary effort that I am aware of and that seems to be making progress towards a verified rustc suitable for safety critical work.

Ferrous Systems is working with AdaCore and just released the Ferrocene Language Specification [2] to formally document the Rust subset that Ferrocene will use.

[1] https://ferrous-systems.com/ferrocene/

[2] https://ferrous-systems.com/blog/ferrocene-language-specific...


Rust is supposed to be a better C++, and resoundingly succeeds at that goal.


It partially succeeds at that, because while it has a much better story in being safe by default, there are plenty of C++ use cases where Rust still hasn't a story to sell.

HPC, HFT, GPGPU, LLVM/GCC infrastructure, GUI, console SDKs, drivers SDKs, security certification ,....


Ok, fair, you’re right. Rust is successful in a rather large subset of C++ niche, but not yet the whole thing!


imo, Julia is a better fit than rust or C++ for hpc/gpgpu


It might someday, still lots of room to improvement regarding current workloads.

I not not seeing Fermilab or CERN doing real time beam processing in Julia anytime soon.

Or stuff like having graphical shader debugging tools for Julia.


Julia already is starting to be used for high energy physics (see https://arxiv.org/pdf/2003.11952.pdf and https://www.youtube.com/watch?v=QlfAa-LN1SA for details). It's definitely not the default yet, but there absolutely is effort to use it for particle accelerators.


Ick, most programmers aren’t going to write MISRA C/C++ either. Even if people claim they do it seems way to easy to just turn off or ignore it. Take the recent reports on the Toyota gas peddle bugs. They’d completely abandoned.

Gotta say SPARK does seem to provide much of what it claims. Interesting that NVIDIA seemed to be using it for their secure bits.


Quoting one publication about MISRA [1]:

"From the data obtained, we can make the following key observations. First, there are 9 out of 72 rules for which violations were observed that perform significantly better (α = 0.05) than a random predictor at locating fault-related lines. The true positive rates for these rules range from 24-100%. Second, we observed a negative correlation between MISRA rule violations and observed faults. In addition, 29 out of 72 rules had a zero true positive rate. Taken together with Adams' observation that all modifications have a non-zero probability of introducing a fault, this makes it possible that adherence to the MISRA standard as a whole would have made the software less reliable."

[1] https://repository.tudelft.nl/islandora/object/uuid:646de5ba...


Its so hard for me to think someone actually thinks this.

Rust really is a great programming language that solves a lot of other problems other languages don't. It does so by introducing a pretty clever paradigm.

The rust community is the least toxic programming community I've ever seen. Leaps and bounds away from go lang, python, and light years away from c, etc.

Like use your head, is vba therefore the language which everyone tried and loved and had to move on from? You're trolling yourself lol. Rust is great but yes you have to learn it and yes that is tricky at first. Join a rust chatroom or discussion board and give it a whack.


> Rust really is a great programming language that solves a lot of other problems other languages don't. It does so by introducing a pretty clever paradigm.

Were you around when Scala was the end all be all of programming shiny things?

"Early on, Scala rode a wave of hype that frankly surprised even me: hype around pushing syntactic boundaries, hype around reactive architectures, hype around functional programming, hype around the Apache Spark project. Much of that hype has since died down, and there was a period of backlash and negativity both within the Scala community and outside of it. Since then, even the backlash has faded, and what is left is a reasonable, boring language steadily advancing and providing a great platform for general software engineering."

source: https://www.lihaoyi.com/post/TheDeathofHypeWhatsNextforScala...

Not every concern needs to be solved at source level. My brief crit of both Scala and Rust is that they do not take a modular approach and instead have opted for a 'comprehensive' approach that necessarily entails (arguably) unreasonable levels of complexity at syntactic and semantic layers of source code.


I appreciate your view on scala and rust. I was around when scala became popular and wrote it in industry for a while. It wasn't a great time.

I think rust differs from scala in what it is trying to do. I also think rusts' complexity is backed by functionality that defines it's paradigm. Scala on the other hand has a few too many 'i think this would be nice to support' features in it that make it messy to deal with.

Rust imo isn't messy in that regard. Does scala still have it's place, sure. Does rust have it's place, yes.

Also if you read the posts on here, there's a lot less hype going for rust than the other way around. It's success isn't really due to it's hype, it's because people like what it does for them. Lots of people hate on it, usually baselessly.


Sorry for the offtopicness, but could you please stop creating accounts for every few comments you post? We ban accounts that do that. This is in the site guidelines: https://news.ycombinator.com/newsguidelines.html.

You needn't use your real name, of course, but for HN to be a community, users need some identity for other users to relate to. Otherwise we may as well have no usernames and no community, and that would be a different kind of forum. https://hn.algolia.com/?sort=byDate&dateRange=all&type=comme...


I was making new accounts for each different topic I posted on. For example I only used this account for this entire topic. I'll stick with crabby grabby. Sorry didn't know.


Appreciated!


I don’t like Scala, because it seems everyone who makes a library has their own little DLC I have to learn as well.


I’ve hardly said anything about Rust (and I’m actually learning it at the moment). My point is that stackoverlow’s most loved metric can be misleading. It’s more of a least-wanting-to-jump-ship-right-now metric.


You're not wrong. Being an exdata geek, I can say almost all metrics are flawed. We could even look at the most popular language and realize how that is flawed/not very meaningful too. Thanks for clarifying. Didn't mean to get in your case, but it just didn't sit well with me. I see a lot of people bashing rust in here, who have kind of obviously never tried to learn it.


> Rust really is a great programming language that solves a lot of other problems other languages don't. It does so by introducing a pretty clever paradigm.

Rust's "pretty clever paradigm" lifts a large set of low-level concerns into the application domain, and consequently makes them the responsibility of the application programmer.

This makes sense for a subset of programming contexts, where the application programmer needs to have and assert specific positions in those domains, in order to produce viable programs.

The problem is that, overall, very few programming contexts actually benefit from this level of specificity. An HTTP service implementing a business-level capability absolutely does not give a shit about ownership lifetimes. The fact that Rust "solves" this category of issues is completely irrelevant to this class of program.


Definitely not. I've been a full time rust developer for a long time now. Whenever I need to write some C# or Go or JS I honestly feel quite blind with a hand tied behind my back. I don't have the expressiveness of rusts type system and I don't have the safety of the strong compiler so I have to test my code a lot more thoroughly to be confident. With rust I'm pretty confident in my code from the start


Can support this - I'm a full-time C# SE but learning Rust on weekends has taught me so much and gave me an entirely new perspective when it comes to reasoning about memory and data structures.

I don't know why but haven't seen many posts on how the combination of Rust's trait system, implicit conditional returns and strict enforcement of im/mutability of state allows one to handle significantly higher amount of states the application can take in the same amount of code. Other languages usually have you writing thousands of lines of verbose error handling and state validation code and traits allow for a superior way to compose behavior over standard interfaces / abstract classes.


What does Rust's compiler tell you that C#'s doesn't? You still have guaranteed memory safety in C#, and the type checker will verify against all type errors.

I realize that Rust's compiler might catch more concurrency problems, but your comment is written as if you feel "blind" even writing single threaded code.


Rust's advantages don't stop at concurrency or type safety. In my experience, the type system is actually much more concise and the APIs are a lot more explicit than any other language I've tried. It's clear when the argument you're passing is going to be mutated or not and move semantics help a lot on designing good APIs (not having to remember to close a File or being able to use it after it's closed, for example). Not to mention sum types with pattern matching, being expression based, etc. I also find that Structs and Enums being values instead of references (as opposed to Classes in other languages), reasoning about the code is a lot more straightforward, which goes back to my point about explicit mutability. A huge part of it also goes to great libraries created by the community, that usually cares about API soundness.

It's very common in Rust to do a big refactor or write a program from scratch and have it work on the first or second try, which may release a good amount of dopamine for some.[0]

Not saying the language is perfect, but it can feel pretty good, to the point of being addictive, while also freeing to know you can think less about the variants and let the compiler do it for you, and the reliability of the created program is usually pretty amazing. It can also be annoying, specially when you're learning it and try doing something in a way that's just not viable in an easy way (e.g. manually creating a Linked List).

[0] https://old.reddit.com/r/rust/comments/uixup6/just_wanted_to...


Rust's match is a lot more powerful than C#'s third party OneOf type alone


> Whenever I need to write some C# or Go or JS I honestly feel quite blind with a hand tied behind my back. I don't have the expressiveness of rusts type system and I don't have the safety of the strong compiler

How would you compare it to Typescript? Having become a recent convert, I feel the same way going back to Javascript now


Typescript is great, but it is ultimately a gradually typed language that is built around compiling to Javascript, and that has extensive interaction with untyped Javascript code.

You often end up with obscure issues that a good type system should prevent. Maybe because the third party typings for a package are faulty or incomplete, maybe because the compiler just gave up on a complex expression and fell back to any, or because the developer just gave up and used `as any`.

Typescript is also really constrained by keeping JS compatibility. A prime example is the lack of real sumtypes. Instead you have to use objects with a string tag and do if/switch on that tag to disambiguate the concrete type, which is incredibly awkward when compared to proper compiler sum type support.

I'd much rather use Typescript than Javascript, but it's far from perfect.


Yeah, there were many times I was programming TS, and was very surprised at what the type system permitted. I started to realize type safety was best effort, or at times even performative, but by no means something TS can guarantee.


I'm not the same person that you responded to, but I feel much less secure in TS than in C# due to the fact that typing is not a requirement, and that type definitions might differ from the actual library/framework code. It's still a big improvement over plain JS though.


That's a really helpful perspective. Thanks.


How you feel relates to you and your preferences and doesn't really say anything about Rust versus let's say Go.

Is your software more performant and does this translate to additional customers or reduced costs? Is your software more stable and does this result in reduced support costs or happier customers?

Testing effort is likewise not a decisive matter. In fact it's quite likely that what one wins time-wise on the testing side is lost on the development side.


Not the person you're responding to, but imo the main thing missing from Go is ADT's. After using these in Rust and Swift, a programming language doesn't really feel complete without them.

That said, I think Go's simplicity has a lot of advantages over Rust for a great many use-cases. Imo Rust almost feels like a prototype for a great language which will finally get ownership-based memory management right. The goals of the language are admirable, and the tooling is great, but it's such a complex language once you start getting into topics like lifetimes and async.

I think it shines for certain use-cases where the tradeoffs it makes genuinely add value, but in a lot of ways I think it's more of a niche language for people who love esoteric programming topics rather than something with the potential to go truly main-stream.


>> the main thing missing from Go is ADT's. After using these in Rust and Swift, a programming language doesn't really feel complete without them

What are the differences between an ADT (plus pattern matching i’d reckon?) in Rust/Swift vs the equiv in Go (tagged interfaces + switch statement)?

One has exhaustive matching at compile time, the other has a default clause (non exhaustive matching), although there’s an important nub here with respect to developer experience; it would be idiomatic in Go to use static analysis tooling (e.g. Rob Pike is on record saying that various checks - inc this one - don’t belong in the compiler and should live in go vet). I’ve been playing with Go in a side project and using golint-ci which invokes https://github.com/nishanths/exhaustive - net result, in both go and rust, i get a red line of text annotated at the switch in vscode if i miss a case.

Taking a step back, there isn’t a problem you can solve with one that you can’t solve with the other, or is there?

To take a step further back, why incomplete?


I'm not a go expert, but imo the main difference is ergonomics and clarity. Rust/Swift style ADT's plus pattern matching gives you a very concise and readable way to declare and use sum-types, and the Go way seems to have more boilerplate.

Also with Rust for instance you have more robust pattern matching. So you don't have to match only on type, you can match on complex criteria (i.e. foo is a Circle, with foo.radius < 10).

I find this type of programming very expressive and easy to reason about.


>> I'm not a go expert

Yeah me neither, i’ve just been dabbling for fun recently. I’ve been dabbling with rust for longer

>> the Go way seems to have more boilerplate

    …
    switch t := s.(type) {
    case Circle:
      if t.radius < 10 {
        fmt.Println("the rust syntax for this is sweeter")
      }
    …
https://go.dev/play/p/s4TTZeo7Gse

Definitely less boilerplate in the rust version, but i don’t think i go along with it being incomplete or less clear.


I think this is less clear than. The rust/ swift version.


That’s fascinating, what would you say obscures clarity?

Go: https://go.dev/play/p/s4TTZeo7Gse

Rust: https://play.rust-lang.org/?version=stable&mode=debug&editio...

For me, i reckon the Go type machinery is more verbose in this case, e.g. the isShape method to tag Circle as a shape - that just feels awkward to me.

The cyclomatic complexity is identical for both though.


Yeah exactly, imo the way the Go version requires you to declare an interface, in this case with a no-op method essentially acting as a tag, and declare conformance on your types is quite noisy and feels like a hack.

Also I prefer with Rust-style sum types that the declaration happens in one place. In the Go version your Shape types could be scattered around all over the place, which makes it harder to parse and understand if you're reading unfamiliar code.


This Go code is wildly non-idiomatic. Type assertions via `.(type)` are a tool of last resort, not something that an application developer should turn to as a solution to a problem, and certainly not post-1.18, which permits generics.

edit: e.g. https://go.dev/play/p/wDO5J8CElSC


Hey thanks for sharing this, I think this has lost track of the problem though, remember we're looking for the alternative to rust's:

    enum Shape {
        None,
        Circle(radius: usize),
    }
In your version we've lost the Shape concept, to make it more explicit, what's the idiomatic go version of:

    enum Shape {
        Circle(usize),
        Rectangle{length: usize, breadth: usize},
    }
https://play.rust-lang.org/?version=stable&mode=debug&editio...


There is no way to express an enum whose possible values are of different types.

In Go code will typically "offer" concrete types, and "accept" abstract interfaces. Abstractions over concrete types are expressed by consumers who want to operate on those types, rather than producers who provide implementations of them. So your Shape would probably end up an interface defined by whatever consuming code wanted to treat Circles and Rectangles equivalently.


Rust and Go are surely different classes of programming language. Rust is a systems language and Go is garbage collected. That is, Go is in the camp with Ruby, Python and Javascript, whereas Rust is in the camp with C and C++. Garbage collected languages are easier to use than non-garbage collected languages, so if you can use them, you should.


Why is a systems language used for web applications, servers, command-line utilities and all sorts of libraries?

The article is about a “messenger bot” for example and nobody’s complaining that it’s wrong to write such a thing in Rust.

The reality is that Rust is competing with Java and Go and Python for many things and its poor ergonomics are hobbling it.


Probably comes down to your definition of a systems language.

E.g. if that means implementing low level things like cryptography APIs, or being able to define the exact memory layout of objects in memory or access raw pointers or write ASM inline then obviously that disqualifies ruby, python and js but it would mean Go qualifies.


No it's not. There are tradeoffs, definitely, and one of them is visible in the article: at the moment doing lifetimes and async is hard. But you don't have to do it, most of the time you use `Arc` or `Arc<Mutex>` and call it a day. In async web frameworks you very rarely need explicit lifetimes, because the workload is mostly isolated - a handler gets an input from the request, you compute the output, you return it. Any shared state is typically behind a shared pointer (like `Arc`).

I feel like this article is written from a perspective of a library author that always starts with going for zero allocations generic API. In production apps you very rarely do that, usually it's plenty fast anyway.


If you default to Arc everywhere, aren’t you essentially just implementing a slow GC?

This type of thing comes up of often when people try the language. They re-implement some part of a program, originally written in a fast GC language, and then wonder why it’s slower.

I feel like the power of the language comes through in specific workloads, or when you take the additional time to avoid naive code. That’s why it is so verbose and rich, it gives you more control. And this is something that advocates often clearly state.


> If you default to Arc everywhere, aren’t you essentially just implementing a slow GC?

Like I posted earlier, you don't do this everywhere, just some sporadic use where it makes life a lot easier. It doesn't have to be all or nothing.


As @therockhead replied already: you won't put every single variable behind `Arc`. It will only be for shared state: queues, handlers that you need to move between threads/tasks etc.


> In async web frameworks you very rarely need explicit lifetimes, because the workload is mostly isolated - a handler gets an input from the request

Was going to post the same comment. Most of my hobbyist Rust programming has been via the Actix Webframework and I only run into the most trivial of borrow checker issues. I guess my projects are not complex or interesting enough :).


Rust makes it easier and faster to create certain classes of applications, specifically applications that originally would be written in C and C++. Things that are hard in Rust, are even harder in C and C++. So Rust is liberating and 'rewriting' complicated applications can be satisfying because you can move faster. For me personally I am playing with Wayland and display streaming and it is very satisfactory so far to be doing this in Rust, whereas I would not want to try this in C++. The code I am writing is much simpler than the existing C++ code.


"Things that are hard in Rust, are even harder in C and C++."

Incorrect. This handler-dispatcher problem illustrated in the article is utterly trivial in C++ and many programming languages. No need to struggle and stretch your brain as if you are in the Math olympiad.

I am learning Rust myself and I think Rust fans are spreading misinformation and propaganda by saying Rust makes things easier than other languages. No, Rust makes things VERY difficult - and you need to study and learn the Rust way of doing things - which is significantly different from other programming languages.

We need a BIG design patterns for Rust book - which takes lots of common design problems and shows the idiomatic Rust way of doing it.

But just stating that C++ code for a given design problem is harder than Rust is utterly wrong and demonstrably false. Rust tooling is definitely simpler. Rust coding is definitely not.


This handler dispatcher problem gets trivial if you do it in unsafe mode. Just transmute all lifetimes to 'static and call it a day. That is what you do in C++ all the time (implicitly). So C++ version of it would be easier to get compiling, but harder to get right - because you'd have to prove lifetimes are correct anyways.


Would you agree that it is "easier to do it correctly?" Because rust makes lifetimes explicit? I think that's what rustaceans are trying to say generally.

I don't think anyone is trying to claim that rust is some trivial language. It's not. But it makes systems level concerns explicit, flying blind is much harder in my opinion. The complexity is technically the same, but the language has training wheels that other languages don't.


"Correct" isn't a boolean condition of a program.


> Things that are hard in Rust, are even harder in C and C++.

That is not true of C++. There are many valuable things that are much easier to express in C++ than Rust, owing to C++ being a significantly more expressive language. Rust also doesn't make it easy to write software where ownership is intrinsically ambiguous and must be algorithmically resolved at runtime without wrapping the object, a common case e.g. for high-performance storage.

I would agree that everything is harder in C, though.


Where's the proof that Rust makes it easier and faster to create applications? In my experience it's harder and slower compared to other languages like Go and even C++, but you get memory-safety in return while keeping a very good runtime performance profile.


I have been way more productive with Rust than with C++.

For instance, I haven't yet had to debug weirdly muting memory, deal with the immense nuanced possibilities of doing the same thing (there's a reason for CPP core guidelines), stuff like the rule of five, writing cross platform cmake files that include various libraries, ...

Not proof for a general statement, but another example from a Rust adaptor


Rust removes a lot of the debugging and performance tuning, that happens later in production. Is it easier/faster while you are learning. Nope. When you understand it, sure it could be. This depends on the person. Just like how someone might be faster or slower at a specific framework within the same language.

Imo I write programs faster than other languages because the compiler helps me out. Your mileage may vary.


>Things that are hard in Rust, are even harder in C and C++

This is absolutely not true. Something hard in Rust but almost trivial in C++ (via fold expressions): mapping or folding a function or operator over a tuple of heterogeneous types. E.g. to sum over a tuple of arbitrary numeric types:

    auto mySum = std::apply([](auto... x){ return (x + ...); }, myTuple);


This is a pretty weird example. Why do you want to sum over a tuple of different data types in the first place? This kind of has a code smell I can't put my finger on...

Fwiw rust doesn't let you dynamically index tuples, because rusts' take on tuples is different.

Should your tuple actually be a struct with a "sum" method on it? Imo probably. Or should you have your numeric types be the same type for better memory layout, maybe...

Just because another language let's you do something doesn't mean you should do it. Kind of like in js, does it make sense to divide a number by a string(not sure if you can do this but guessing it's valid js), probably not, is it a feature or a bug, you decide. Should this be part of say the kotlin standard, probably not.


Wouldn't this be a nearly identical call, but specifying the add trait? I'm still learning so I'm not sure if I'm missing something


I think I'm quite fad-resistant (others would use less positive words to describe the same attribute). I still find Rust truly excellent, and the most joy I've had programming since Haskell (while at the same time being a lot more mainstream and pragmatic choice for collaborative projects than Haskell).


My wife calls my stubborness 'Cultural Stamina', I think it's an excellent phrase that always raises a smile.

I really enjoyed Haskell when I tried it years ago (2004) and I definitely agree that Rust is much more apropos to the mainstream.


> Cultural Stamina

Love it!


Rust is young, very ambitious, of course general purpose enough to do everything in it, but its ecosystem has serious gaps. (And some of those are dependent on planned language level features.)

...

I spent a lot of time reading r/rust, various blog posts before going beyond helloworld in it.

To me it's in the same category as Scala (ZIO) or TypeScript. Both are very powerful, a joy to work with them, until the low-leven limitations hit in (JVM or JS).

However I don't interpret that as a sign of oh we need to go back to assembly, but more like, okay, we need to accept that our tools and the problems we use them on are not in harmony (yet).


Totally agree. Scala and TypeScript are both usually wonderful to write.

Though I might argue that one of Scala's biggest issues in my eyes, performance, is mostly _not_ a JVM limitation.

For example, a Scala for-loop calls functions on each iteration, and immutable containers need to be garbage collected for each modification. Both of these could be compiled away in many common cases (like C++ or Rust do, but Scala's compiler doesn't, unless they've changed that in the last couple of years).


Oh I don't think the performance is bad, the JVM is an amazing technological platform, but it uses a lot of RAM, it's GC pauses are bad for latency, and the Scala/Java/JVM ecosystem is simply not that high quality as Rust's. (See all the security issues, log4j2, jdk ecdsa rewrite, just to name the few that come to mind in the last few months.)

And for TS I don't think I have to mention the quality of the underlying JS ecosystem :)

On the other hand, of course Rust is still on 1.x, GAT is still on the roadmap (though the RFC recently entered into final comment period (or how it's called), yaay!, and then a bunch of legitimate criticism was submitted..., so it might still take year(s))


I don't have too deep knowledge of Scala compilers, but Scala 3 is a huge revamp so I wouldn't be surprised to see it change. Though both of the mentioned cases seems to be easy to "fix" by the JIT compiler -- the JVM is really good at inlining and short-lived objects are almost free.


Did scala 3 finally clean up the syntax. Scala is a difficult language because there are so many ways to do things. I ran away from it after dealing with it professionally off and on for a year.

Which is a shame because I did a hobby project with it and it was super fun and liberating compared to old java.


> Did scala 3 finally clean up the syntax

Well, they didn’t break the existing language, so not sure. It depends on what do you find readable/difficult. Because contrary to the usual opinion on the language, I believe it is not “difficult” - it has much fewer exceptional rules than Java for example. Sure, some features are more expressive and that comes with big responsibility, but to actually answer your question, some implicit usage is indeed cleaned up making it much less magical-looking.

But scala 3 has been a very huge update, including having a new compile flag that will turn to language “null-safe” (so a nullable String will have String | Null as a type). So it might be worth it to have a new look at the language.


Null safety sounds great. My big gripe was all of the symbols and how they had different meanings in different contexts. That said, in most cases it's not a real problem, but with a team you can end up with some messy stuff.


Yeah I agree that operator overloading should be used very sparingly, I often dislike it in Haskell as well. Fortunately it seems to be less and less often used in modern libraries.


I’d say no. Been doing Rust for 3 years now and I have decided that I will never again accept a job offer that makes me write C++ or Java.


I actually feel this way about C++ to some extent. I love that C++ has zero overhead abstractions. I hate that to use them requires programming in the most obtuse and indirect meta language.

If you ever read, I think it was Modern C++? Where they point out the huge "trick" in C++ was someone figuring out you could make a compile time branch by declaring arrays of size 0 or some such nonsense. They then wrapped that feature in a template so you could then try to use it. At some point they formalized it so it's no longer based on arrays of size 0 but still, read any boost library and look at how unreadable it is. It might be nice to use, but it shouldn't be so hard to write!

But, I think the fact that it is hard to write brings joy indirectly to many programmers. They get a dopamine hit for "solving the puzzle of finally getting their cryptic incantation to work". Maybe they write a bitset class. It takes 500-1000 lines of code. Or maybe they make a lighter weight fixed size array and again it's 1000+ lines of template code. They forget that the goal of coding is shipping, not having fun solving the incantation puzzle.

It doesn't seem like it take 1000+ lines to do these things.


An application developer spending hours refining a method/class/function to it's most optimized form is usually not worth the time. It's only going to be used in the application so the ROI is much lower.

The author of a library with wide usage spending hours refining a method/class/function to it's most optimzied form may actually be worth the time because that effort is amortized over hundreds or even thousands of applications. The ROI is much higher in that case.

Determining when it's correct to make that tradeoff is an important part of the job. Boost probably makes the correct tradeoff. But your average C++ application dev might need to make a completely different one.


It's not a matter of smarts but grit. Modern society cultivates short attention spans, impatience, and a need for instant gratification. It's really uncomfortable, and costly, for many to spend hundreds of hours cultivating a new skillset. So, many give up shortly after starting to pursue it. However, those who persist and achieve capabilities come to value what those capabilities offer over alternatives.


If you ask an embedded developer (as in bare metal, no OS), who is also into electronics, instant gratification and especially instant feedback, is what actually makes you choose this path of interest in the first place.

It's a matter of style and character how you cultivate new skills, and Rust wants you to cultivate them in a certain, some people are just not made for. YMMV.


I'm an embedded developer, and for me it's the opposite. Not saying everyone is like me, just saying not everyone is like you. I find regular software development to provide more instant gratification, I like the result of systems interacting with each other physically. Something about that just feels really cool to me. So much that I spent a few years as an FPGA developer, designing hardware and writing drivers for it, and also writing C on a soft core microcontroller running on an FPGA, touching registers that configure things, messing with i2c busses, I just find it all really amazing, in the same way I find car engines spinning at 6000+rpm and managing timings is incredible. Regular software development has faster results and gratification, at least from my perspective. And to be clear, I'm not saying you're wrong, or that your perspective is any less valid than mine


Rust is really great for a large subset of problems where there are really no good alternative. (Low level problems, where the next best alternative is C or C++. And if C++ looks better than C, it's probably not low level enough.)

But if you deviate from those, into higher level programs, a language with garbage collection will always be much more productive than Rust. So we have a set of people doing the things that Rust does best, and celebrating that they have a great language, and a set of people trying to fit the square language into a round hole, and complaining that it doesn't fit at all.

Added to that, there is a wide space of problems where high-level languages do not have appropriate support, but you can always hack your way in with a low level one. Those are the worst, because there is just no good option, there's just one that you can beat into working.


I am interested in Rust because of its safeguards around multithreaded programming. This is is my main motivation to learn it.

What I've found good about rust is its modern toolchain and documentation.


The hardest multithreading related bugs are deadlocks, which Rust doesn't prevent. So this "fearless concurrency" mantra is not entirely true.


The documentation to get started is outstanding with Rust


The advanced documentation is also incredible and crystalized a lot of cs concepts for me. There is no impedance mismatch between the beginner docs and the advanced ones, they reference extra learning materials... Super greatful for everyone on the documentation team.


Read the rust book and practice for two weeks, you'll get the hang of it. It's just not a language you can pick up 80% of it in a day. Like BASIC or Go or something


No, it really is wonderful once you make it. Which resources have you used to learn?


I did ok with Rustlings and I read the 'The Book', I'd say I am largely struggling with async and lifetimes.

I have spent most of my career in C, C++, Objective-C and have recently tried Zig, which I enjoyed, possibly because of it's brevity, and I read through the Jakt programming language docs, which was much more familiar to me but I think if you only used Rust with ARC it would be a simple language to adopt so that's not really a fair comparison.

I think what I really need is a project rather than learning resources, with time being our greatest enemy, I need motivation to get over the hump so to speak.

(Like I said, I might not be smart enough, or I might just be profoundly lazy).

Thanks for your reply.


I've been leraning rust with a pet project of mine (an Apple2 emulator). That was a bit too complex for a start as I had threads and a bit of architecture to structure my code correctly. But in the end, I know understand how rust does threads and memory allocation and I'm now much less intimated by the type system. I still don't get the lifetimes.

Moreover, a lot of the libraries in rust needs you to understand the type system thoroughly sometimes to use them, and some of them use the typesystem to enforce some specific behavior (without telling you :-)). For example, the logger mechanism in rust makes it very hard to dynamically change the logger implementation at run time but it doesn't explain why (in the end, I think it has to do with thread safety, but I'm not sure).

It took me about the equivalent of 30 full days to get there. Although I'm an experienced programmer (C++,assembly,Java,python,R), the last 15 years have been python 99%. Had I continued with C++ all those years, I'm sure I'd understand rust much better.

So, just keep going and really listen to the borrow checker. The thing is really smart and sometimes, after a lot of pain, you understand that your own mental model was wrong :-)


> Moreover, a lot of the libraries in rust needs you to understand the type system thoroughly sometimes to use them, and some of them use the typesystem to enforce some specific behavior (without telling you :-)). For example, the logger mechanism in rust makes it very hard to dynamically change the logger implementation at run time but it doesn't explain why (in the end, I think it has to do with thread safety, but I'm not sure).

Mainly because logger is a static value, if you really want to change your logger at runtime, then you have to pay a little bit for synchronization (i.e. locking with mutex), other than that, it's not that hard.


There are some very practice oriented books for rust: zero to production, rust in action. And a third one that I didn’t read, it is game programming focused and seems pretty good. Something with “handmade”.


I believe the game programming one you are thinking of is “hands on rust” by Herbert Wolverson. I haven’t read all of it, the parts I have read are quite good but I’m not big into games so I switched over to rust in action.


That's actually one of the reasons that I asked. I am the author of Rust in Action and wondered if the person having trouble had investigated one of the more practical resources.


Sounds like survivor bias :)



It's a language designed by people who's favourite language is not even pronounceable.

Did you think that such a group of people, who place their love for the language above practical things like readability, would come up with a new language that cared about the user-experience[1]?

As we see all the time WRT to programming languages, readability is more important than the more abstract stuff.

> I hear all the arguments about CVEs and wonder if rust will reduce the number of these problems simply by disabling the programmers that create them.

That sounds like a different way of saying "the global number of CVEs will be reduced by reducing the number of applications written". After all, if you "disable" the programmers who write systems programs, they aren't going to get magically replaced by programmers who don't write systems programs.

You're just gonna have fewer programmers.

[1] A language is an interface between a user and their problem. If this is not highest priority of a language design, the language may never take off in any meaningful sense. See Monads.


I personally don't like Rust (I like to have a garbage collector for what I do), but I don't think it's a hard to read language.

Readability is an incredibly subjective thing. For example, APL might look like an absolute mess to most people but to the people who know it, it's incredibly easy to read. All "readability" means in this context is that it's familiar to you.

In my opinion, the only truly hard to read languages are languages that require you to keep large amounts of context in memory while reading a specific part of the codebase, be it due to lack of support for abstractions for proper encapsulation, messy overloading, insane inheritance hierarchies, or something else.

EDIT: Readability also requires you have a codebase that's well written, and even that's subjective.


> For example, APL might look like an absolute mess to most people but to the people who know it, it's incredibly easy to read.

But if we use that as a bar ("you have to know it"), then all languages are equally readable.

Pretty much all the popular languages converge on similar syntax an/or grammar.

You can say that it is because that particular set of syntax is the first, or you can say that languages that didn't have similar syntax was abandoned by developers.

There is an equal evidence/lack of evidence for either claim.


GP brought up a thing that’s certainly not equally represented in all languages. There are physical limitations for reading, and the amount of novel context you can juggle.

There is a balance between verbosity and conciseness that makes code more or less readable to different people.

If you have few experts who are maintaining a codebase over a longer time, then verbosity gets in the way. If you have a wider skill distribution and fast turnover, then you want verbosity.

Additionally I think there are more objective features. Like ambiguity, simplicity, formatting, naming, visual hierarchy...


> It's a language designed by people who's favourite language is not even pronounceable.

Elaborate?


This opinion seems to be very sure of things.


My CVE comment was very much tongue in cheek.


> My CVE comment was very much tongue in cheek.

I got that, but the point is still very much relevant. If places switched to Rust from C++ (or Go, or C), they'd write less software because there will never be as many people who understand Rust as there are people who understand Go.

If it was at all easy to pick up there'd be a fewer stories from people who tried learning it and abandoned the effort.

I cannot think of any person who reported abandoning Go because it was too hard to learn.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: