5 ms·
Everything that's hard in Rust could be solved by GC. With Rust, programmers have to spend most of their mental energy worrying about management of memory, whi
by zelly 7y ago
Everything that's hard in Rust could be solved by GC.
With Rust, programmers have to spend most of their mental energy worrying about management of memory, which has largely been automated already.
I always go back to this quote from Andrei Alexandrescu (creator of D):
A disharmonic personality. Reading any amount of Rust code evokes the
joke "friends don't let friends skip leg day" and the comic imagery of
men with hulky torsos resting on skinny legs. Rust puts safe, precise
memory management front and center of everything. Unfortunately,
that's seldom the problem domain, which means a large fraction of the
thinking and coding are dedicated to essentially a clerical job (which
GC languages actually automate out of sight). Safe, deterministic
memory reclamation is a hard problem, but is not the only problem or
even the most important problem in a program. Therefore Rust ends up
expending a disproportionately large language design real estate on
this one matter. It will be interesting to see how Rust starts bulking
up other aspects of the language; the only solution is to grow the
language, but then the question remains whether abstraction can help
the pesky necessity to deal with resources at all levels.
RAII and borrow checking is a crutch. You just limited the set of programs you can write to those that can be written in the block-lifetime-scoped manner, which is smaller than the set of good programs (see: pretty much any graph-heavy data structures). The limitations of this programming model show up everywhere, like in the way closures have to be implemented.
There will be more innovation in GC that will make manual memory management even more useless. In a lot of cases the JVM does a better job of freeing memory than a programmer. I don't want to spend my time programming worrying about the same thing (memory) that K&R did in the 70s. I don't want to bet against innovation and technology.
- jcranmer 7y ago> You just limited the set of programs you can write to those that can be written in the block-lifetime-scoped manner, which is smaller than the set of good programs (see: pretty much any graph-heavy data structures). Given that most of my Rust programs have involved graph-heavy data structures, I'd like to see you explain why it's impossible for me to have written what I have written.
- zelly 7y agoNot impossible, just harder. Ceteris paribus, it would have been easier to write those programs in Python or Java. It's not like this is not well-known. Rust users admit it. GUIs are hard to write in Rust because of the limitations of RAII+borrow checker based memory. You have to rely on ref counted pointers which can become very complicated to deal with in cyclic dependencies and long-lived references common in GUIs. This problem is not unique to Rust either. C++ makes it hard to write GUIs too, but hacks are used to get around the language like Qt's moc or Microsoft's old CLI extensions to C++. All non-GC languages are crippled for application programming. Sure, there are domains where GC cannot ever work, like signal processing or kernel dev. In these places I'd much rather see Rust used than C++.
- im_down_w_otp 7y agoThis indictment makes little sense to me considering that, outside the Rust compiler itself, the largest early and still ongoing use case for Rust was/is Servo. A web browser engine, which is predominantly a thing that's dealing with multitudes of graph-shaped problems. :confused:
- wahern 7y agoHave you looked at the issue tracker for Servo? The bugs and pain points are enlightening. Plus, Servo isn't even used in production! The strategy has been to move parts of it. AFAIU, the most complex piece so far has been the CSS engine. That's nothing to sneeze at, but still. I recently wrote a full PKIX X.509 DER decoder in LPeg in a couple nights of hacking; have fun doing that (or writing anything equivalent to LPeg[1], for that matter) in a language without GC. It's absolutely possible, just like it's possible to implement it in ATS or Coq, but that's not the point of debate. That said, it's one thing to admit the costs of Rust's model. It's another to argue about the implications of that cost--i.e. the degree to which it makes Rust non-viable long-term. On that point I have no opinion, except to say that for complex application development I've been very happy using Lua as a glue language, and many others have been happy using GC'd languages for complex logic. But that's more of a neutral factoid as it both diminishes Rust's relative costs and benefits. Whether it augurs in favor of Rust or not depends on your starting point. Plus, language success is less dependent on merit than we'd like to believe. [1] Note that LPeg is far more than a PEG engine (like Rust pest), as strict PEG engines are incapable of parsing DER, which is context-sensitive. In addition to its extensions (e.g. runtime matches), what makes LPeg so simple is that you don't even need intermediate graph representations. You can transform subtrees in the grammar inline, mixing function transforms and intermediate captures to your hearts content. This is difficult to explain and more difficult to appreciate until you see and use it in action.
- TheDong 7y ago"You just limited the set of programs you can write to those that can be written ..." Yes! That's awesome! I want the set of programs I can write to be small, but still large enough to contain correct programs. For example, I really like statically typed languages! But what is static typing? It's rules that reduce the set of valid programs. In a dynamically typed language, 'def double(x): x*2; double(os.Open("foo"))' or other such nonsense is a valid program that errors out at runtime reliably. In a statically typed language, that program is not valid. Woo! That's a whole class of programs that do bad stuff which aren't valid anymore! If rust restricts the set of valid programs to those that structure the ownership of data more rigidly, I'll take it! I do realize that rust has escape hatches that let you model those things when you need to, but I'll gladly take a language that pushes programmers away from difficult to reason about data-ownership-models even if it doesn't prevent all such cases.
- otabdeveloper4 7y agoIf you want a garbage-collected language, there's already literally a thousand of them out there. Including dozens that are more popular than Rust.
- shmerl 7y agoEvery GC is a trade off. You can't replace RAII with GC without losing some control. No matter how much you innovate in it, you have to pay with something. That's the whole point of GC after all. Here is a good read about it: https://blog.plan99.net/modern-garbage-collection-911ef4f8bd8e https://blog.plan99.net/modern-garbage-collection-911ef4f8bd...
- pjmlp 7y agoGC enabled systems programing languages don't replace RAII with GC, they offer both and its up to the developer to make the best use of them.
- shmerl 7y agoIf the language works without GC, you can implement optional GC for it. Even Rust had something like that in the early days (though it was dropped). But languages where GC is expected by design, don't allow you to disable it (like Java).
- pjmlp 7y agoExcept I wasn't speaking about Java, rather D, Nim, Modula-3, Active Oberon, System C#, Swift.
- imtringued 7y agoGargabe collection is a much bigger crutch. Once you use it your entire program is contaminated by the performance characteristics of a single improperly written function. You cannot mix real time code with non real time code. If you do your real time code will be delayed by the non real time code. The unpredictability of the GC has become a property of your entire application.
- zozbot234 7y agoYes, but you can have other kinds of cycle-aware memory management, which integrate better with their surrounding code than plain tracing GC. E.g. something like https://github.com/artichoke/cactusref https://github.com/artichoke/cactusref which can collect cycles deterministically, and does not have to trace the whole heap to do so (which implies a lot of hidden overhead in plain GC, because all heap-allocated structures must then be legible to the tracing routine).
- zelly 7y agoYes, but let's be real, 95% of programmers do not build real-time systems. Especially not the type of programmers Rust is appealing to. They seem to be more excited by WebAssembly than the stuff that actual low latency people worry about, like tuning obscure FPGAs and vectorizing math code. These are industries like audio processing, SpaceX, industrial equipment manufacturers, self-driving cars, high frequency trading. Definitely not code targeting x86_64 cloud VMs or iPhones. In hard real-time environments they do not even do memory management. They just statically allocate the whole heap and never malloc or free while the program is running. So even if Rust is better at memory management, it won't make them switch from C because it wasn't an issue.
- lifthrasiir 7y agoFirst of all, Andrei Alexandrescu is not the creator of D. > With Rust, programmers have to spend most of their mental energy worrying about management of memory, which has largely been automated already. This is a common misunderstanding. I think the word "automated" is misleading, and suggest that we should look at two phases of memory management: the plan and the execution. In traditional low-level languages like C, you plan how to manage memory and you write code to execute that plan yourself. Your code may not match the plan, thus all sort of problems ensues. In languages with GC, you are allowed to not think how to manage memory and GC will execute their own inferred plan... until it is not. At some point you are forced to think how to manage memory and also tune GC and/or code to fit to your belated plan. This point may not be reached (simple scripts) or can be delayed much further (good modern GC), of course, so it still remains very useful. In (a typical use case of) Rust, you plan how to manage memory but give that plan to the compiler to check if the plan is executed correctly. The compiler also generate code for common executions that you don't have to. So the execution is mostly automated (or rather, delegated), while planning is not. A common theme here is that you can't avoid at least the planning once you've got past a threshold. If GC would supplant even that planning, you won't need value types at all; isn't that what the generation hypothesis is all about? But many languages with GC but not value types now get them. While it can be argued that Rust's affine typing is not sufficient to capture some common memory management patterns [1], that fact doesn't diminish the value of explicit memory management planning, and thus Rust's. [1] And I think it is actually true! Indeed, I believe affine typing plus GC can be actually better than affine typing or GC alone (and value types mimic a good subset of this). There are some Rust libraries for tracing GC (e.g. [2]) as a starting point. [2] https://github.com/Manishearth/rust-gc https://github.com/Manishearth/rust-gc
- openfuture 7y agoI think Gluon is a good example of how Rust can be 'bulked up'. The idea is to have a DSL inside Rust that essentially has haskell semantics. This allows you to write performance sensitive code in Rust and then marshall it into Gluon where you can do high level manipulations with type safety before you unmarshall into a performance sensitive section again. To me the failure of Rust is more that it didn't go full-on-haskell syntax wise and (to a lesser extent) that there isn't a specification (or some standards) beyond the test suite.
- wtetzner 7y ago> You just limited the set of programs you can write ... which is smaller than the set of good programs That's true of all static type systems. Also, the whole point of Rust is to cover cases where performance and memory management are important. If you can use a GC'd langauge for you program, then pick one of the many fantastic existing ones.