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

Mostly spot on.

That said I can seriously see Rust giving C++ a run for it's money in about 2-3 years. All these things you have to learn the hard way(ownership, move semantics, dangling pointers) are dealt with up-front in Rust. They really aren't bolted on as an afterthought but a core part of the language(std::move I'm looking at you!).




I agree, but again that's for new code. Many times you'd be going in to an existing codebase like he mentioned. Especially in the areas he mentioned like Financials, HPC, or Compilers. You might get away with Games because even though the engines are reused the code is mostly written to be thrown away to make it faster.


Yup, that's why I say 2-3 years. It's going to take some time.

I also think there's some interesting work to be done w/ language integration so you can drop Rust into Java/C#/Ruby/etc. I think this is actually the best way to drive adoption since you don't need to greenfield it. Tricky part is going to be making sure you preserve the correct lifetime guarantees but I don't think it's insurmountable.


That sounds incredibly naive. Three years isn't a long time, especially when C++ has a 30 year head start.

People put too much emphasis on low level language features when promoting new languages. The pitfalls that Rust solves are known issues in C++, and there are known solutions to them and best practices for avoiding them. A lot of the problems are "solved" as new iterations of the standard come out.

To really give C++ a run for its money Rust will have to compete with the gigantic ecosystem around C++. It has libraries for literally everything. It's backed both directly and indirectly by all of the biggest software companies in the world. It's supported by debuggers, profilers, memory profilers, static analyzers, IDEs, refactoring tools, and editors. There are books, tutorials, training classes, etc.


> The pitfalls that Rust solves are known issues in C++, and there are known solutions to them and best practices for avoiding them. A lot of the problems are "solved" as new iterations of the standard come out.

What is the known solution for memory safety problems, in particular use after free?

(It's not RAII and smart pointers.)


I'm pretty impressed by ASAN (and MSAN, UBSAN, etc.) It catches uses after free trivially, as long as you have unit tests, which I always do.

I wonder at the cost of these 2 strategies, for the huge legacy of C/C++ infrastructure we have:

1) refactoring it to be testable, adding unit tests, adding test coverage automation, adding ASAN/MSAN builds, etc. (LLVM is a game changer IMO in addition to C++ 11; things have changed so much in the last 5 years)

2) rewriting it in Rust

I'm not claiming anything specific, but #2 seems strictly more expensive, since you still need unit tests for logic bugs anyway (and yes I have written OCaml and get that you can replace control flow with typed data, etc.) #1 also has a straightforward migration path.

More to the point, most open source software has TERRIBLE test hygiene. If they don't even have time to write tests, I wonder how they will have time to rewrite in Rust.

I'm all for new software in Rust, but I'm thinking about all of Linux user space, web servers, web browsers, every programming language implementation, etc.

Also, fuzzing can be combined with ASAN.

https://blog.hboeck.de/archives/868-How-Heartbleed-couldve-b...

Yes it would be better to know these things statically and not dynamically, and I'm glad that Rust has innovated in this space.


ASAN has not been successful at eliminating (sometimes exploitable) use after free bugs in the wild. For example, look at this year's Pwn2Own. All browsers are heavily unit tested, fuzzed, and run through tools like ASAN, in addition to making heavy use of smart pointers, and they all fell to UAF.

There is a reasonable argument to be made that memory safety problems don't happen enough to be worth eliminating in practice (though people are often reluctant to make this argument so explicitly). But I don't think it's possible to successfully argue that they can be eliminated at reasonable cost in C++ with the tools we have today.


For one, compilers usually ship debug stdlibs that will zero out freed memory and freed pointers, so debug builds will seg fault when deallocated memory is accessed.

Improving on that, Valgrind can find issues like use after free pretty easily, and even tell you where something's freed and where it's used again. Coverity does a great job on that, too. Coverity can even tell you when you access a pointer or shared pointer without checking if it's non-null.

On top of that, handling "raw" pointers and memory has fallen out of favor, and the preference is to use references as much as possible, which are more difficult to use incorrectly.

I won't claim any of those solutions are 100%, but they're sufficiently close that few people will jump to a new language over it. In my experience, "real world" C++ programmers don't spend much time fighting memory safety problems.


References are not harder to use incorrectly. They are just as vulnerable to UAF.

Additionally, the security track records of large-scale apps written in modern C++ disagree with you. For proof, go to any browser bug tracker, or look at Pwn2Own.


You're really kind of changing the subject and trying to put words in my mouth here.

The reality is that apps in every language have security vulnerabilities and bugs, and different languages are more or less susceptible to different classes of bugs. Nobody is claiming C++ is perfect, and it's irrelevant to this conversation.

Getting back to my original point, even completely solving the memory safety issue, getting mainstream adoption for Rust will require competing with C++'s other advantages, like its huge ecosystem, and I think it's optimistic to think that will happen in just 3 years.


> The reality is that apps in every language have security vulnerabilities and bugs, and different languages are more or less susceptible to different classes of bugs.

Memory safety problems are on the whole much more problematic than the types of bugs that other languages admit, especially memory-safe statically typed ones like Rust. That's because they regularly result in remote code execution, which is among the most severe kinds of security issues. Nobody's claiming that Rust eliminates all security vulnerabilities: just a large number of the most severe ones.

> Getting back to my original point, even completely solving the memory safety issue, getting mainstream adoption for Rust will require competing with C++'s other advantages, like its huge ecosystem, and I think it's optimistic to think that will happen in just 3 years.

Sure, no argument there in terms of replacing C++. But I think that the idea that "C++ is too entrenched, other languages won't be able to compete" is very '90s thinking. Look at how dominant C++ was in the '90s compared to its status today. In the early-to-mid-'90s, you wouldn't think of building your company on anything but C++; nowadays, building your company on C++ (outside of a few niches like games or embedded software) is uncommon enough to warrant a blog post.

What I think is likely to happen, if Rust succeeds, is that it will continue the trend of chipping away at C++'s dominance in areas where Rust's advantages are strongest (safety, concurrency, friendliness to newcomers). It won't replace C++ wholesale, of course; C++ is immortal.


>>The pitfalls that Rust solves are known issues in C++, and there are known solutions to them

Known issues and solutions that are known to experienced C++ developers. The article is specifically talking about newcomers.


2-3 years? Try 10 or 15 or more. Any serious code stick around for a long time.


I would love to use Rust more, and have enjoyed working with it on some toy projects, but the last time I looked there wasn't a super solid general purpose math library. Is there anything out there for Rust that is of similar scope to C++'s Eigen or Python's NumPy+SciPy? What about SSE/AVX intrinsics from Rust?


I really wanted to use Rust for numerical/scientific computing tasks, but it's kind of miserable for it. I didn't get hung up on the ownership things that all of the Rust zealots talk about (although I think explicit lifetimes are needlessly complicated). I got hung up trying to implement simple things like complex numbers and matrices in a way that was generic and usable. I'm sure some Rust fanboy will argue that Rust has operator overloading through traits, so I'll challenge anyone to make a workable implementation such that zA and 2.0B works in the following generics:

    let z = Complex<f64>::new(1.0, 2.0);
    let A = Matrix<f64>::ident(10, 10);
    let B : Matrix<Complex<f64>> = z*A;
    let C : Matrix<Complex<f64>> = 2.0*B;
If Rust can't do scalar multiplication or real to complex conversions, it's really not usable for what Eigen or Numpy can do. Try defining the Mul trait generically for those multiplication operators, and you'll see what I mean.

(yes, I know there are some syntax errors in the type declarations above - It's my opinion Rust got that wrong too...)

Supposedly this kind of thing will eventually be possible with the recent "specialization" changes, but I haven't seen anything that allows operators to work as above...

ps: Last I looked, there was fledgling support for SIMD on the horizon... LLVM supports that, so it could happen.


This is essentially a complaint that Rust went with strongly-typed generics like every statically-typed, non-C++, non-D language instead of untyped templates like C++ and D. I think that the difficulty of reasoning about template expansion type errors, the complexity of SFINAE, and the consequences for name resolution like ADL make templates not worth the added expressive power for Rust, especially when the features needed to support your use case can be added in the strongly-typed setting eventually.


I don't think that's quite right... ISTM that it's more about lack of multi-parameter type classes/traits[1] (+ specialization, I guess) and the fact that it went with the traditional non-symmetrical dot-based notation for dispatch... which means that the first "trait-parameter" would always be "privileged" (at least syntactically).

[1] At least I don't think it has those yet, right?


Rust has had multi-parameter traits for a very long time - possibly they were never not multi-parameter. All of the binary ops are multi-parameter. The first parameter is just an implicit Self parameter, which does preference it syntactically, but semantically it is not privileged in any way.

The issue that operator overloading math crates come into is that Rust's polymorphism is not only type safe but also makes stronger coherence guarantees than systems like Haskell do. You can't implement all of the things you want because Rust guarantees that adding code to your system is a "monotonic increase in information" - adding an impl is never a breaking change to your public API, and adding a dependency never breaks your build. Haskell does not make these guarantees.

There's no way to "solve this" entirely because there are a bunch of desirable properties for type class systems and they fundamentally conflict, but I think with specialization and mutual exclusion (the latter hasn't been accepted yet) Rust's system will be as expressive as anyone needs it to be while still maintaining coherence.

Of course in this context Wadler's law should be taken into account, and the grandparent poster could maybe revise their strength of opinion about syntactic sugar and recognize that this is about solving a much more complex problem than how to make matrix multiplication look nice. https://wiki.haskell.org/Wadler's_Law


I stand very much corrected. I must admit I wasn't sure and just skimmed a little documentation and didn't see any examples of MPTCs.

> The first parameter is just an implicit Self parameter, which does preference it syntactically, but semantically it is not privileged in any way.

Yes, but I think the syntax was actually what bothered the OP who was complaining about linear algebra. At least C++ has free functions for operators. (I assume, again without knowing, that Rust doesn't, otherwise OPs "demands" should be easy to meet, given specialization.)

I mean any kind of "double * matrix" or "vector * matrix" or ... should be easy to support if operators are free functions and there's MPTC and specialization. EDIT: Actually, come to think of it, for this situation (algebra) you don't really need specialization, you just need overloading. (Since none of the types involved are sub-types of each other. It could be argued that a 1xN matrix ~ N-vector, but that's probably not worth supporting.)

Generally, I just think it's a mistake to even support the magic "dot" notation and thus privileging one operand over any other, but I guess we're getting off topic.

Thanks for the lesson, btw! :)


Again, the issue we run into is with coherence. The Rust team decided that adding a dependency should never in itself break your build, and adding an impl/instance to a library should never be a breaking change. Haskell doesn't make this guarantee. C++ doesn't even typecheck parameters.

Providing this guarantee means establishing what are called orphan rules: you can only `impl Trait for (Type1, Type2, ...)` if a certain portion of those traits and types are defined within the same library as the impl (the exact rules are nuanced, there's an RFC that defines them). The rules that were arrived at as providing the best guarantees unfortunately make it difficult to implement the operator overloading traits in the way a lot of numeric libraries want.

For example, you can't define a trait `Integer` and `impl<T: Integer> Add<T> for T`.

I'm actually not sure what the OP's specific complaint is, but its ultimate cause is something along these lines.


> This is essentially a complaint that Rust went with strongly-typed generics

It could also be a complaint about how operators are implemented, e.g. in Scala they're just methods (no need for a special trait). That's not to say I don't think Rust made the right choice, but Scala went with strongly-typed generics, and can allow implementing the asymmetric multiplication operators.


If operators are just specially named methods, then with strongly-typed generics you can't write generic functions that work on anything that (for example) implements the + operator, because traits (concepts) have to have a specific signature.


Yes, you're right. The only way I can think of to handle it (in Scala, I suppose you can't do it in Rust) would be via implicit parameters. You would basically have a Times trait, and a TimesOp trait.

    trait TimesOp[L,R,O] {
        def times(L left, R right): O
    }

    object TimesOps {
        implicit object ScalarMatrixTimesOp[S] extends TimesOp[S,Matrix[S],Matrix[S]] {
            override def times(S left, Matrix[S] right): Matrix[S] = {
                ...
            }
        }
    }

    trait Times { self: L =>
        def *[R,O](R right, implicit timesOp: TimesOp[L,R,O]): O =
            timesOp.times(this, right)
    }
I'm sure I got something wrong here, but I think the basic idea works. In any case, it goes to show that getting this behavior in a language with strongly-typed generics is non-trivial.


No. The complaint is that Rust is not good at expressing numeric algorithms. The poster above asked about a Rust library like Eigen (C++) or Numpy (Python)... It doesn't matter - I suspect you would dismiss any criticism regardless.


I've been looking Rust with good eyes and I want to be using it in my future projects in College. But how easy would it be for developers to "give up" OOP for a more safe and up-front language like Rust?

I mean this as a serious question, cause I see C++ being used instead of C thanks to its multi-paradigm capability and I don't know how Rust could fight that for now.


You're not really giving up OOP with Rust, traits give you interface abstraction which is most of what you're getting with C++. As I write more C++ I find myself using less classes and more structs + functions that let me decouple my code and data.

If anything I would say Rust is a tad more multi-paradigm due to its really strong functional roots(Sum types!) and nicer treatment of lambdas(no alloc like in std::function).


Maybe a bit off-topic, but I just want to clarify - lambdas only include dynamic allocation if you convert them to an std::function, right? I was under the impression that 'auto f = []{...}' did no heap allocation, but converting to an std::function could, depending on the size of the closure.


Yup your on the mark, it leads to some interesting scenarios where you can't easily refactor code without either introducing template hell or taking the hit for std::function.


Rust is currently lacking plenty of "quality of life" features which even C++ has (eg, default parameters). Not to mention a good IDE. I do think it's the first serious contender to eventually replace C++, but it's really not there yet.

It's definitely worth trying and learning. I would've ditched C++98 in a heartbeat to move to Rust, but C++ is a pretty exciting and productive place to be ever since C++11.


I haven't needed an IDE in Rust. The auto-generated documentation is usually good enough for all my needs. However, C++ is pretty awful without an IDE, because you can easily end up with deep object hierarchies, usually with two files per object.

It's also nice to just tab to your terminal and do `cargo run` and get your code compiled out of the box. Writing a decent makefile (or whatever else you plan to do) for C++ is comparatively quite a hassle.


From a code writing perspective, Rust's support in Atom and other editors thought Racer is pretty good. Debugging is my big issue right now. For that I drop into lldb in UI mode, which works fine, but I would love to see that integrated into one of the ide's out there.

Anyway, the lack of an IDE hasn't hampered my ability to be productive in Rust. Unlike Java, C++, et al.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

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

Search: