At my $DAYJOB I write a lot of Java, and modern full-featured IDE's for Java like IntelliJ are absolutely awersome for refactoring. Most common refactorings are fully automated, and many more complex things are very easy to do by combinding some of the base refactorings.
I really like writing Rust in side projects, but after getting used to the phenomenal support refactoring support in Java, having to follow the compilers diagnostics feels very primitive.
I'd hope that as Rust grows in popularity the tooling will come from that so I'd keep an eye on the intelliJ rust plugin or rider support for rust because as you say, it's really difficult to go from a day job where for example promoting a local variable to a parameter (with replacement at the call sites) just works to one where you actually have to think about manual refactoring.
Patches are welcome! https://areweideyet.com/
The point I was trying to make is that the view that Rust is great for refactoring depends heavily on what one is used to. For example, as compared to any dynamically typed language, a strongly typed language will be better for refactoring.
Writing refactorings that work reliably is very complex, and I'm not sure if it is practically possible to write the same kinds of refactorings that Java has for Rust. Two of my favourite refactorings in IntelliJ are extract method (with automatic duplication finding) and inline method/expression. I think that such refactorings are a lot more complex to do reliably in Rust due to ownership and borrowing rules, unnameable types, and so on.
It is interesting seeing the difference in peoples expectations on what an IDE can and should be able to do for you depending on what they are used to working with.
I do think that there’s a relationship between power and usefulness, but more power isn’t always better. I’d rather use Ruby than Java 1.5, but I’d rather use Rust than Ruby. YMMV.
BTW I didn't say it was impossible, only that it doesn't play nice and probably is no longer a pure HM system. The search space is definitely much bigger with overloading and subtyping.
End result actually looks surprisingly familiar to someone coming from C++ or Java, at the first glance. It's really a shame that it's not something that OCaml is famous for; it deserves to be. I wish I could have an object model that expressive in C#.
[1] https://caml.inria.fr/pub/docs/manual-ocaml/objectexamples.h...
That has always been my refactoring algorithm with C++, C# of TypeScript now. I know a lot of smart people using dynamic languages but I always prefer to lean on the compiler to tell me what needs to be changed.
As someone who has been working mainly in Rust for about a year and is now starting to pick up Python, this is huge! I pretty much never write Python that isn't explicitly typed thanks to how Rust changed me as a programmer.
Rust is a nice language for threaded programming, but the async situation is a trainwreck 4 years in the making.
I was thinking if the language itself, where it needs to keep backwards compatibility with Java (the distinction between case classes and classes, for example) and over engineering (implicit action at a distance all over the place). I think Scala is a nice language buried in way too much syntactic sugar. Interestingly enough, Rust's syntax doesn't bother me but quite a few people seem out off by it.
Rust is new and it advances slowly but at a steady state. Given its immaturity in some areas I can only go off potential and the async story seems to have a bright future, despite it's somewhat underwhelming present.
Strange to see Go suddenly brought in to support Rust like this. Was it Go that killed said interest or Rust? Why is Go relevant here?
Python still has a fair bit of expressive power that Go and Rust would struggle to provide, but I think both can be compelling alternatives in different cases, and they offer a lot in exchange (such as, full type safety and improved performance.)
I realize Rust offers much more safety than Go, but both of them are eons ahead of C++ in this regard. When you're starting from nothing, any level of guarantees is a huge shift.
There's really no proof that systems written in Rust have better reliability compared to systems written in Java, Typescript or PHP, is there? I've recently had the same discussion with someone claiming that FP offers stronger correctness guarantees than OO languages: where's the proof?
Furthermore, Rust doesn't offer "much more" safety than Go either, in fact Go's GC suggests that it's harder to make memory handling errors in Go compared to Rust. After all Rust's still vulnerable to memory leaks.
Finally, comparing C++ and Rust reliability is much more nuanced than your dismissive attempt. Modern C++ written by an experienced team + good tooling can have really good memory safety, not as good as Rust, but good enough so that the other advantages of C++ can tip the balance in its favor. The problem: many projects don't use modern C++, or they don't have experienced devs or they neglect the tooling. But here's the kicker - those same teams are unlikely to use Rust anyway.
Here I expect Firefox or Chrome to be given as counter-examples to which I's say that it's likely impossible to write a memory safe browser in C++, due to the project dynamic. Remains to be seen if it's possible to do it in Rust.
Absolutely disagree. Those are exactly the teams that will choose Rust over C++. It is well known that many shy away from writing plugins for node or python in C/C++ specifically due to the fact that they don't have enough experience with these unforgiving languages. The gap between Python/JS and C/C++ is wide and deep. But the use case is still there. If you have to improve performance of a component - Rust provides a lower barrier to entry and will be chosen by such teams.
In my experience they just fix their bugs and move on with their lives. Probably you were thinking of some other teams, since you're mentioning plugins for Python.
I am not here to prove mathematically that Rust results in more correct programs than PHP. I am here to claim that I believe that it does.
To me one of the biggest obstacles to writing correct code is not just memory safety. It's preventing unintended uses of code. It's handling every case.
PHP is a memory safe language, but that does not mean it is equally good for writing complex software. Why? Because:
- Exception and error handling in PHP, including the standard library, is inconsistent and tricky to get right. In Go and Rust idiomatic error handling is pretty easy to get actually correct.
- Code is not only not type safe, but you might not even notice when you violate type safety. Many things that are runtime errors in Python and compile time errors in Rust or Go are incorrect behavior in PHP.
- The TypeScript, Rust, and Go compilers and toolchains are more rigid, because more strict languages make that possible. For example, if you fail to return in every possible code path of a function, that's an error. In TypeScript, any unchecked possibly null access is an error when using strict nulls. Many more examples exist.
>Finally, comparing C++ and Rust reliability is much more nuanced than your dismissive attempt. Modern C++ written by an experienced team + good tooling can have really good memory safety, not as good as Rust, but good enough so that the other advantages of C++ can tip the balance in its favor.
OK, it feels like you're just being contrarian now. I've made this same argument before as a reason why we shouldn't all just rewrite everything in Rust.
I've worked on a fair bit of large C++ projects before. My current employer, Google, does quite a great job with the C++ toolchain, and admittedly while I do not have as much experience with it as I do C++ outside of Google, I'd say it's close to the best I've ever seen.
And even then... It's ass ugly, the errors are confusing as hell, I can't understand what the hell is going on in some of the macros, and it's still possible, with metric tons of safeguards, to fuck up and segfault (guilty.)
Something C++ fans (including me) love to point out is that if you enforce the use of smart pointers you effectively can prevent whole classes of memory issues. In reality I'm pretty sure everyone knows that's a bit of an exaggeration. It's still pretty easy to misuse a smart pointer. And on top of that, smart pointer syntax can be confusing. I used to be a huge proponent of operator overloading but after not having it for a while I'm pretty sure it has a tendency to turn verbose code into confusing but terse code.
C++ just has too much fucking syntax. And it has templates. And on top of that syntax it has text macros. And even if you ban new macros, you still need macros for very basic things like "logging with line numbers". And it's useful for things where none of the other available tools solve the problem. So good C++ code probably ends up using a lot of macros even if most of it is not defining new ones.
People have made C++ fault tolerant as much as possible because they have to. There's too much C++ in the world to stop and rewrite it all in some memory safe language. No amount of language debates on Hacker News will ever change that.
But, we should not let that cloud the fact that better C++ doesn't come close to providing strong safety guarantees, and it sure doesn't prevent obscene looking code. As much as people will hate Gofmt, I've never seen uglier code than some of the edge cases as handled by clang-format. (If you know of a C++ formatting tool that's any better, please tell me.)
So does Rust result in more correct code? Does Go? I believe so yes. For starters, C++ error handling is atrocious. Some people use exceptions, some people don't. Google uses StatusOr[1] and I think the best case would be something like Andrei Alexandrescu's expected<t>. In reality you get a mix of custom status codes, C style error handling, weird OOP style error handling where objects contain error statuses (especially when you can't throw in a constructor.) Even at Google there are third party libraries, with both C and C++ APIs, so there's still some mismatch that has to be dealt with. The standard library is just as guilty here.
How about safety? Even with improvements it's really hard to make a subset of C++ where you can't accidentally segfault. Sometimes, you have a smart pointer and you need a regular pointer. So what do you do, dereference? Well sure... But now what are you thinking about? Lifetimes. And thus, the value proposition of Rust. Go solves the lifetime problem with garbage collection, but in C++ you just have to manually, as a human, figure out what lifetimes are expected, and in the meantime someone could submit code that subtly changes this and when you submit your code now head is broken even though neither person made a mistake.
The list really could go on for a long time. And I expect every point here to be disputed because there's some way to mitigate the problem. Reflect for a moment, though, that all the energy spent trying to mitigate problems like these could've been spent on writing better code elsewhere if it weren't for the shortcomings of the language.
1: http://www.furidamu.org/blog/2017/01/28/error-handling-with-...
Once again, where's your proof? You know, studies, experiments, demonstrations comparing real-world (or even dummy) projects and concluding the above? Because gut feelings aren't going to convince me, or any other questioning individual.
Almost all these claims, including yours (not surprising at all) revolve around the idea of encoding relationships and allowed operations in the type system. I'm calling this "reliability in the small", or the ability of writing statements and functions which are restricted from performing specific non-desired operations. These do have a positive effect in my opinion, but not enough to result in more reliable systems overall. A pretty well known tenet of safety engineering is that putting together reliable components does not mean one gets a reliable system.
Frankly, I think it's other things that really make a difference: thorough code review, formal specifications, design by contract, automated testing, taking time to gather requirements and design things.
I'm not going to spend time addressing your points regarding C++, because let's be honest, you wrote way too much :-/ In principle you're correct to say that it's easier to write memory-safe Go or Rust code. C++ requires more effort to get there and C++ teams tend to prefer performance to safety.
It is not easier to write correct Go or Rust code compared to C++. Memory access violations aside, there are many more bug classes which aren't prevented by any of those languages. Rust is constantly being oversold, there's nothing that makes it any better than say Java or Swift, on the contrary, the former are much easier to pick up.
I explicitly said no. I'm not here to fulfill your personal requests. If that's what you want, Hacker News comments are probably the wrong place to ask, and I'm not personally interested in conducting such studies. I'm already convinced, so it wouldn't really benefit me much.
>Because gut feelings aren't going to convince me, or any other questioning individual.
OK. This isn't gut feelings though. It's a discussion about subjective matters.
If that was too much writing, then so is any meaningful discussion about the differences between programming languages. I'm not going to attempt to discuss this further.
If you're not providing that proof because it's beneath you, or for some other reasons you've really just wasted everyone's time here by repeating the same appeal to feelings and personal experience for the Nth time.
I addressed the core of your arguments against C++. The rest has been discussed before by myself and others. It's nothing new on HN.
(You could of course use a ECS-like pattern in Rust and end up with a half-baked reimplementation of a Go or LISP runtime, but the ergonomics would not be there.)
I have not much experience with go, but my feeling is that it should be faster to have something working, and then if it’s worth it (e.g. if it needs high performance with concurrency), migrate to rust.
We all have been in the situation where we quickly put something together. With Rust -- you internalize some of the things you know the compiler will demand -- so tenth time you write something in Rust will be faster. But the beauty is that Rust compiler will force you to _gradually_ fix the design of your tool and the extra time you spend fixing it pays dividends when this code eventually becomes something everyone relies on.
Coding in Rust is like an investment: it requires some commitment and slows you down initially (for the right reasons!), but pays huge dividends and return grows exponentially over time.
Kind of my point. Sometimes you don’t want to make an investment, sometimes you just need something to show.