Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> a Manhattan Project to build a fast Rust compiler

Or work on getting what Rust gives you in a different language that isn't Rust (maybe entirely new, maybe not[1]).

One underdiscussed thing about Rust is that it's so clearly a byproduct of the C++ world. And the most disappointing thing about Rust is that it probably won't ever be seen as a prototype that should be thrown away.

1. http://mbeddr.com/



If you want to convince people that Rust should be thrown away in favour of mbeddr or something else, you need to make an argument based on specific design flaws of Rust, not just tar it by association with C++.

That argument would have to not just explain why an improved language is needed, but also why Rust can't evolve into that language via the edition system. It would also have to convince people that whatever benefits the improved language brings justify moving away from the existing crate ecosystem, tool ecosystem, and developer pool, and building new ones (or how you would reuse/extend/coopt them).

(In reality I think the influence of Haskell and even node.js were as important to Rust as C++.)


    >not just tar it by association with C++.
To build on this and your last paragraph: I think it's arguably a feature of Rust that it combines:

- A syntax that's highly familiar to the legions of C++ programmers already out there

- A bunch of features C++ has had in the works but that aren't quite there yet (specifically, a proper module system comes to mind)

- Features from ML/OCaml/Haskell, like a first-class option type, first-class (powerful) pattern matching, and an emphasis on immutable-by-default variables

Having this without the cruft of the decades of backwards-compatibility that C++ has had (not without good reason, granted) makes Rust the hard refresh of C++ that I and hopefully others have been waiting for for a while.


.NET has these features for decades. It compiles really fast, much easier to use than C++, and has awesome IDEs.

C interop is pretty much same as in Rust.

GC is not an issue in modern .NET even for resource-demanding apps running on slow ARM CPUs. Here's an example: https://github.com/Const-me/Vrmac/tree/master/VrmacVideo BTW it consumes non-trivial amount of C APIs like V4L2, ALSA, and audio decoders.


The reasons .NET never really competed with C# for the longest time were a handful:

- First-party support for .NET only existed on Windows systems until 2015ish with the release of Rosetta

- Third party support across platforms via Mono never really picked up steam for a number of reasons

- Early on, .NET code, much like JVM code, wasn't in the same league as C++ in terms of performance

- I'd like to be proven wrong on this one, but .NET remains a poor framework to do systems programming in. GC is IMO still a factor because even though modern M&S GCs are impressively performant they still add a degree of unpredictability to your runtime, and sometimes that's not acceptable — so reference counting or something even more basic is preferred, if only for the consistency.


> .NET remains a poor framework to do systems programming in

Have you clicked that link? Essentially, I’ve re-implemented parts of ffmpeg’s libavformat and libavcodec in C#. On Raspberry Pi, the software uses 15% of CPU time while playing 12 mbit/sec 1080p video, on par with VLC, while using 20% less RAM than VLC. If that’s not a system programming, then what is?

BTW, I don’t think I allocate any objects on heap while playing the video, therefore no GC is involved, and no degree of unpredictability is introduced. Wasn’t hard at all, just recycling buffers between frames.


Object recycling often works fine to avoid GC issues for simple stuff, but in more complicated applications you really do need to dynamically allocate and free memory and GC is going to get involved.


> for simple stuff, but in more complicated applications

Media engine part of the library has 45k lines of code, this is mostly due to the complexity of V4L2 API, and of the MKV and Mpeg4 containers. I wouldn’t call that “simple stuff”.

> you really do need to dynamically allocate and free memory

Memory allocation in .NET ain’t limited to GC.

First of all there’s stack. I use Spans + stackalloc in quite a few places there. Modern .NET even has these `ref structs` where the compiler guarantees they are never accidentally boxed into the heap.

Another thing, no one stops you from using malloc/free, like I did in that class: https://github.com/Const-me/Vrmac/blob/master/VrmacVideo/Aud...

Finally, the mere presence of GC doesn’t affect performance in any way, only usage of GC does. Even for latency-sensitive applications like that media engine it’s OK to allocate stuff on managed heap, as long as it only happens on startup, or otherwise rarely. I allocate quite a lot of stuff on the heap, megabytes, when opening a media file.


Funny, before your comment showed up, I was actually going to edit in an addendum to link to

https://robert.ocallahan.org/2018/10/the-costs-of-programmin...

... to pair with the mbeddr link.

You seem to be at a place where you think of Rust as already entrenched, but I'm at a place where I still see Rust as a proposition—one that could lead to that place, or not if we think better and nix it (following the reasoning above).


I don't think Rust is going away. You may not like it; it may not be adopted by the Linux kernel. But it is widely used in real codebases (including, say, Firefox). It's not brand new. And the article linked above discourages creating new languages; valid or not, that horse is well out of the barn.


The post as written, and whether intended or not (admittedly by current signs, I guess it'd be foolish to wager anything other than "not"), ends with an observation that's still highly relevant here but that you're neglecting to account for.

> I hope people consider carefully the social costs of creating a new programming language especially if it becomes popular, and understand that in some cases creating a popular new language could actually be irresponsible.

And being widely used is not the same thing as being entrenched, not the same thing as being unable to say, "nice prototype; let's wrap this up now and do it for real this time".


> ends with an observation that's still highly relevant here but that you're neglecting to account for.

No, that's kind of the sentence I was responding to. Rust is already popular; that horse is out of the barn.

> And being widely used is not the same thing as being entrenched, not the same thing as being unable to say, "nice prototype; let's wrap this up now and do it for real this time".

I don't care to argue about the first clause, but I don't understand how you can argue the latter. Who is going to say "nice prototype; let's discard this?" Do you expect the Rust-using projects to just fold? Do you expect Rust developers to just disappear? Again, it sounds like you don't like Rust, which is fine, but as someone external to the community, why do you think anyone would listen to you about spinning down Rust?


As someone who's spent the last few years writing a 170K line Rust project ... I consider it entrenched!

I stand by that blog post, though I recognise it's controversial. I think Rust clearly qualifies as "worth the cost of a new language". There simply wasn't, and still isn't, any other serious contender for safe GC-free systems programming. New contenders will arise but in the meantime lots of projects are doing safe systems programming that without Rust would have been done in C or C++ and would have had to be unsafe.


Even if the benefits are "worth the cost of a new language", is using the new language worth the cost of it being Rust?


You have not made your argument clear.

Are you questioning whether Rust is simply not good enough to be worth using by anyone? Lots of people, including me, have judged that is worth using for us, both before we tried it and after we've put Rust projects into production.

(BTW once again you have implied there is something deeply wrong with Rust that cancels out its benefits, without saying what that might be. That is annoying.)


You're not seeking answers; in place of anything that would lead to a better understanding, you're asking the questions that make it easier to defend the position you've staked out. (Great job, Brendan!)

If someone released a memory-safe, highly concurrent, systems-oriented version of INTERCAL, you recognize that someone might look at that and say, "Gee, I don't think that's really worth using", and the comment's lack of detail doesn't nullify the substance of what makes the comment true or not? And an opponent could approach in the same way you are now, with the primary goal of "beating" the other participant—by making it burdensome to respond—and by all appearances do so?

It's not my job to painstakingly prepare a perfect, incontrovertible response for a hostile adversary, particularly since absolutely nothing would come of that time investment. If your idea of success is the sound of all your colleagues telling yourselves that you won the conversation and you're on the right track and nothing needs to change because there really aren't any issues... then, hey, that's just fine.


You asserted that Rust should be thrown away, but decline to provide any reasons why you think that. So yeah, in the absence of any supporting argument, I reject your claim, and so would any other reasonable person who doesn't already believe it. You have added nothing to the discussion.


> You asserted that Rust should be thrown away, but decline to provide any reasons why you think that.

That simply isn't true.

> I reject your claim

That's fine.


• Rust is an ML-family language dressed in a C-family syntax to look palatable to existing systems programmers. It's a byproduct of the C++ world only to the extent that it has to work on the CPU architectures and operating systems influenced by C and C++.

• Rust is mainly based on established research and existing languages from 80s and 90s. It's a distilled version of these, not a prototype.

I recommend checking out the first pitch deck for Rust: http://venge.net/graydon/talks/intro-talk-2.pdf


RAII-based memory management without GC, and the concept of ownership vs. borrowing are very C++-inspired concepts. The borrow checker, which is the main innovation of Rust, is automated checking of things C++ programmers spend a lot of effort thinking about.

I think the influence of C++ is much more than just the syntax.


Isn't this more of an artifact of our memory architecture and the way we (de-)allocate memory? In that sense, the C++ flying-by-the-seat-of-your-pants approach and Rust's borrow checker solve the same problem, and I'm sure a lot of C++ insight has made it into the ideas behind the borrow checker, but I'm not sure that makes Rust in a way derivative of ideas extant in C++-land.

To me, the borrow checker just feels like an additional type layer I have to reason and think about. In that sense, my thinking when reasoning about lifetimes in Rust is a lot more along the same lines I do in Haskell than something I would be doing in C++ (which I refuse to code in, I'm not capable of writing secure C/++ code.)


I think the programs that fit neatly into Rust's borrow checking patterns are the same ones that fit neatly into C++(11)'s approach to managing object lifetimes (move/value semantics).

The question is what happens when programs don't fit those patterns. Inevitably in any large real world application, there are some objects with lifetimes that need to be managed carefully and don't match conveniently with some sort of scope in a program.

With C++, this is where one would use std::shared_ptr, or something else. In rust, there's Rc. But either way, you've now stepped into a territory where object lifetimes and bugs can be messy.


I do not find reference counting problematic in practice. In Rust you have to go out of your way to introduce interior mutability in refcounted values, which discourages problematic patterns.

I find that in most cases where ownership patterns don't fit the Rust model, you can abstract the problematic parts into some kind of collection type and hide them in its own crate --- or better still, find an existing crate that does what you need.

The only remotely common case that still doesn't get handled well, in my experience, is the self-referential struct pattern --- when a value needs to contain references to other parts of the same value.


> The only remotely common case that still doesn't get handled well, in my experience, is the self-referential struct pattern --- when a value needs to contain references to other parts of the same value.

There's a basic reason for that, namely you can't memcpy a self-referential structure while keeping desired semantics. Rust now has a Pin<> feature to mark data that should not be moved in memory, but its use is still unintuitive and IIRC requires unsafe. In many cases one should perhaps avoid references to self-addresses entirely; often they can be replaced by indexes and/or offsets.


> There's a basic reason for that, namely you can't memcpy a self-referential structure while keeping desired semantics.

You actually can! For instance, consider a struct with two fields: a Vec<T>, and a &T which references one of the elements of the Vec. Moving the struct (which does the memcpy) does not reallocate the Vec, so the reference in the &T would still be valid. But as far as I know there's no way to represent that in safe Rust; the &T in the struct requires a lifetime, and there's no way to represent "the lifetime of the other field" or even "the lifetime of the struct itself" (something like &'self T).

Yeah, you can use an index in my example (replacing the &T by an usize, and looking up on the Vec every time), but it's not a perfect replacement. A reference would always be valid (and always pointing to the same element), while an index can become invalid if the Vec is truncated, or point to a wrong element if an element is inserted or removed before it in the Vec.


Right, I know what the reason is, but that doesn't stop it from being a problem.


Maybe that has more to do with almost everything new have been garbage collected for the last decades (and that is such a tragedy) and less to do with C++.

It is a low-level programming language after all. Not being explicit about memory would be a bad thing (it almost always is).


I was under the impression that RAII specifically (as opposed to manually calling malloc and free by hand) was an innovation of C++, but I could be wrong.


Ada and Object Pascal also have it.


Don't know, but the concept is very useful and has found its way into many languages, such as thr using statement in C#.

It is just that it is typically more useful/powerful in languages that lack a GC (doesn't necessarily need to be that way though, but my impression).


C# using is Common Lisp's with-....


> RAII-based memory management without GC, and the concept of ownership vs. borrowing are very C++-inspired concepts.

Why are you crediting C++ for an idea that is probably much older than it?


Because it was C++ that made it mainstream.


I'd love to know where C++ got it from, but I can't find it. Any ideas?


I think that's how it started out (and the compiler was first written in Ocaml), but the language has largely abandoned that heritage: the C++ camp is squarely in charge.

In the beginning, I feel like Rust aimed to be a general purpose language, but not anymore. Really the only reason why anyone would consider Rust for a project is if GC was unacceptable. And the amount of complexity in the language just to avoid that is truly staggering.

There aren't that many situations where GC can't be tolerated (and I think some would argue there are zero situations), so I don't actually see Rust as a particularly useful language, and certainly not one in the ML tradition.

Moreover, most zero allocation C code is a total lie. These code bases are littered with arena based allocator that burden the project with all the problems of GC and none of the benefits.

GC works for operating systems, they work for hard real time systems, they work for mostly everything except severely constrained embedded systems.


We have a 170K line project written in Rust (https://pernos.co). I've written a lot of C++ in the past, but also Java and other things (I've been programming for nearly 40 years now), so I'm familiar in developing with and without GC. Pernosco is mostly a server app that could use GC. I'm happy with the choice of Rust.

> And the amount of complexity in the language just to avoid that is truly staggering.

In terms of day-to-day coding this isn't my experience. Once in a while I have tricky ownership problems to resolve, but most of the time I get by just fine without thinking much about the ownership model.

In exchange we don't have to think at all about GC tuning or object recycling, we get RAII, we get to use affine types to encode typestates, and we get easy parallelism. I'm happy about this trade.

As you can see when I started this thread I am far more concerned about build times than I am about the cognitive overhead of ownership and lifetimes.


I have to say my experience with the language has just been very different from this. It absolutely feels like a general-purpose language to me. I actually prefer Rust over Python, as I find the language simpler to use and anywhere from 10-100x faster (if not much more than that in some cases). cargo is much better than pip, and the Rust compiler is much smarter about guiding me than something like mypy.

Maybe I'm unusual in some way, but I do not find Rust hard to use once you've learned the language. You say the complexity to avoid a GC is staggering, but it seems straightforward to me. You have to appease the borrow checker, and you need to learn about some tools like Rc, Arc, Cell, etc., that provide interior mutability. Other than that, the language has been an absolute pleasure and dream to use.

I tend to write Rust the way I write Haskell, not the way I write C++. I start by sketching out all the types that I need to model the problem space at hand. This can be done almost 1:1 with Haskell in many cases. Then I start filling in the implementation, getting me from "input" types to "output" types and only very rarely running into any kind of issue with the borrow checker. Of course, instead of using immutable data structures (as is common in Haskell), I use mutable ones in Rust. The compiler guides me the entire way, and often it feels like an entire program writes itself.

As for GCs, I almost never want one. Performance matters in almost everything I write these days, and faster is always better. Rust is so easy to write once you learn it that I see no reason to accept a GC in 2020 and beyond for any software where performance matters. I do not write software for severely constrained embedded systems. I mostly write real-time backend services that process data or handle large numbers of clients. I could tolerate a GC in much of this, but there's no reason to in a world where Rust exists, and everything is faster, more responsive, and considerably easier to reason about as a result. A few years ago, I would've used a mixture of C++ and Go. Now, I'd just use Rust for all of it.


> There aren't that many situations where GC can't be tolerated (and I think some would argue there are zero situations)

Those people would be wrong. As an extreme example: GPU programming, where GC is essentially impossible due to the architecture.


Can you elaborate on the underdiscussion of Rust as a byproduct of the C++ world?

I'm into Rust, so I guess I assumed it was common knowledge that it was originally written to be like OCaml with better concurrency, and that one of the early goals was to replace C++ in Mozilla code.

But, language-wise, I don't even see that much similarity with C++ except for the philosophy of zero-cost abstraction and the trivial syntax-style of generics being <>.


Rust certainly has C++ attitude to performance, for example 'zero-cost abstractions'. That precludes GC. But this is more indirect influence: targeting the same niche


> That precludes GC

This isn't the case, there are tracing garbage collectors implemented as libraries [1][2], and there is consideration being made for supporting tracing GC in the language and stdlib [0]. As well as reference counted GC having been available in stdlib for a long time [3] (similar to C++'s std::shared_ptr)

[0] https://github.com/rust-lang/rfcs/blob/master/text/1398-kind...

[1] https://manishearth.github.io/blog/2016/08/18/gc-support-in-...

[2] https://boats.gitlab.io/blog/post/shifgrethor-i/

[3] https://doc.rust-lang.org/std/rc/index.html


It precludes pervasive or mandatory GC


I can elaborate, but first: are you a C++ programmer?


I guess some other people here are assuming malintent with your question. Assuming that the answer might be condescending or dismissive depending on how I answer. I'll assume that's not the case and that you simply want to know so you can answer with relevant examples, etc.

I did write C++ code for about 7 years. It was mostly C++98 and C++11.

Since then I've also done a fair bit of Rust. I'm also very familiar with Swift, Kotlin, Java, some lisps, JS, Go, and a few others. So I have enough breadth in language experience for any compare/contrasts you'd like to do.


> I'll assume that's not the case

Thanks, that was actually the right answer! (And those assuming otherwise are not just getting the wrong answer, but I'll point out are breaking the rules[1] here, too.)

The C++-to-Rust background is what I suspected—but the reason had nothing to do with being dismissive about not having the right buzzwords to prove you're smart and well-rounded. (This isn't a job interview, folks, geez.) My instinct was a presumption of deep familiarity.

When I mention Rust having the marks of a being from the C++ world, I'm referring to a property of the language that it shares with Swift. When you say you don't see much similarity, my suspicion is that your first consideration is language semantics and the new affordances, and so when you think of Rust and C++, you're seeing foremost all the ways that they're different, rather than seeing the things that they share. I saw where Hejlsberg once said that he doesn't get why people draw comparisons between C# and Java, and then gives a list of reasons—where those reasons show that his main focus is similar, i.e. he focuses on the way that they differ (and maybe in his case, all the things that he "fixed" with C# in comparison). One of your sibling commenters writes that "Rust is an ML-family language dressed in a C-family syntax", but that's a little off the mark. Rust certainly has a C++-style syntax, but aside from curly braces, idiomatic Rust looks alien when compared to C.

1. https://news.ycombinator.com/newsguidelines.html


> When I mention Rust having the marks of a being from the C++ world, I'm referring to a property of the language that it shares with Swift.

But what property is that?

> I saw where Hejlsberg once said that he doesn't get why people draw comparisons between C# and Java [...]

That's very amusing!

> Rust certainly has a C++-style syntax, but aside from curly braces, idiomatic Rust looks alien when compared to C.

For sure. But I'm still not sure why you say it's from C++ land. It's definitely more like C++ than C, but JavaScript is also probably more like C++ than C. That doesn't mean JavaScript is actually anything like C++, really.

One thing that I thought of that Rust definitely does share with C++ (and C) that other languages (Swift) don't is that you don't have to decide at class definition if a type will be heap allocated or used as a reference vs value, etc. That's decided at the use-site.


C++ programmer of ~10 years here (Google Chrome, mostly).

Rust feels very very much like C++ to me. All the memory ownership stuff is basically common patterns in modern C++ pulled down into the compiler and enforced.

Also arguing with the compiler about types feels very familiar from C++ :-/.


That's a good point. The ownership patterns are basically compiler-enforced best-practices of C++. Fair enough.


Sure, so, what is the actual relationship you see between C++ and Rust?

It sounds like you're arguing that idiomatic Rust looks alien compared to C, which I'd agree with - I'd also argue it's alien compared to C++. But I assume you disagree with that?


Not to throw a mean comment, but i think maybe it can help you in your life by giving you an external feedback :

i hope you don't have this kind of attitude in real life, because it instantly makes you look like an pretentious prick and loose any credit. Your original comment made me curious, and this one loose any interest in what your point of view actually is.

(fyi : HN is (mostly) a developer community with usually knowledgeable people working in the field. if you don't think explaining yourself here is worth it, i have no idea where you think you're going to have the opportunity to give your opinion)


> i hope you don't have this kind of attitude in real life [...] you look like an pretentious prick

Yeesh. I don't even know what attitude you're referring to. You've set out to give some life advice, but do you know how real life conversations work? Can you understand that my response will differ greatly depending on what the answer to that question is? It's pretty normal for dialogues to be... dialogues, which includes checking in with each other instead of monologuing based on a lack of shared agreement.

> if you don't think explaining yourself here is worth it

Once again, what are you even talking about? You're responding to something you've imagined I've said or something you want to attribute to me, not what I've actually said or am thinking.

Can you wait for ragnese's reply and then my response before going off the deep end?


From the guidelines:

> Please respond to the strongest plausible interpretation of what someone says, not a weaker one that's easier to criticize. Assume good faith.

Ironically, by assuming bad faith and a condescending tone in the comment you responded to, you've made a legitimately condescending comment.


Personally, I think the put-down was quite on point. I don't see the point of flagging it, that just leaves the content to imagination.


Anyone can see flagkilled comments, or any [dead] comments, by turning 'showdead' on in their profile.

Just be warned that most of what you'll see is comments by banned users. Occasionally we get emails from people who don't realize that and somehow assume that moderators are condoning the worst dreck that appears there.


> I don't even see that much similarity with C++ except for the philosophy of zero-cost abstraction

That is not really an explicit goal of C++, which is part of the problem rust is trying solve.


Rust is actually a byproduct of OCaml and to a lesser extent Haskell. This becomes obvious the more you use it, especially if you’ve written substantial code in either of those languages before. To really drive this home, I’d wager that you have a better chance of translating OCaml or non-fancy Haskell straight into Rust than you do C++.


> I’d wager that you have a better chance of translating OCaml or non-fancy Haskell straight into Rust than you do C++.

I found that translating OCaml code to Rust is frustrating, because you cannot easily and cheaply replicate the functional approach. It's much more Rustic to take an object by mutable reference and modify it in-situ than it is to take an immutable reference and return a new object. The reason is that in OCaml, you have structural sharing, i.e., multiple pointers pointing into the same data structure, which is a big no-no in Rust, so if you want to replicate the functional OCaml code, you begin allocating a new, complete data structure every time, and that's costly.


Well, of course. Rust is not designed around immutable data structures. There are going to be differences because it's simply not the same language. This [0] example, written by a notable Haskeller, illustrates what I mean pretty well and also touches on what you just pointed out. It's also very consistent with my own experience.

[0]: https://donsbot.wordpress.com/2020/07/04/back-to-old-tricks-...


> And the most disappointing thing about Rust is that it probably won't ever be seen as a prototype that should be thrown away.

Can that ever happen with a language that lots of people use?


JavaScript has entered the chat...


You said two different things about Rust but you did not substantiate anything. What do you mean by

"Rust is so clearly a byproduct of the C++ world"?

Furthermore, in which way is Rust defective to the point that it should be seen as a prototype that should be thrown away?

mbbeddr seems really nice and interesting but it is not just a language. It is a set of integrated tools around one.

Rust shares goals with C++, i.e. it wants to be a high-performance and systems language like C++, but I find the differences to be quite substantial and worthwhile.




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

Search: