Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Comparing Rust to Carbon (lwn.net)
94 points by pykello 53 days ago | hide | past | favorite | 77 comments


I migrated some code from Javascript to Typescript and then from Java to Kotlin. What helped in both cases was that I was able to go file by file. I didn't have to rewrite all my software all at once. That's something that is very disruptive and impractical in software that is actively used (i.e. all useful software).

With Typescript, all you have to do is rename your .js file to a .ts file and then you can start addressing the warnings. With Kotlin, there's a convenient but imperfect Java to Kotlin converter that ships with Intellij. It will get you 95% there but expect to fix a few things. Basically you modify your build to add the Kotlin compiler and then you start converting files. In my case I started with some simple tests that weren't on the critical path to anything. When that worked really well, I quickly got in a mode where any Java file I worked on was converted to Kotlin. Same with Typescript. Both code bases rapidly shifted to being mostly Kotlin/Typescript but with lots of remaining Java and Javascript.

A big advantage of incremental approaches like this is that you get to focus your attention on the most critical parts of the software without really interrupting your development process. The critical parts of your software are those parts that you are actually working on regularly to fix bugs or add features. Another advantage is that you slowly get used to the new language. This takes time. In my case I had to unlearn about 20 years of using Java. Optional is not a thing in Kotlin for example. It's 100% redundant Java clutter. And finally, you organically convert most code that matters in a relatively short amount of time. So, you make rapid progress and make a big impact. Which is always a good thing when learning a new thing.

So, I can see the value of Carbon here. Start dropping it into existing C++ code bases. Upgrade files as you work on the code anyway. Put some focus on the typical hotspots where you were fixing lots of bugs anyway. This way, things improve rapidly and the last 20% of the code is the least important part of the code generally. You get diminishing returns from upgrading it. It will be nice to see what happens when this is ready for production usage.

Like with Kotlin and Typescript, expect this to stay controversial with some people. Stuff like this never fully converts the target audience. I know lots of people that prefer Java and Javascript. Mostly for irrational reasons IMHO. But they do. It all boils down to people just being a bit change resistant. And the C++ crowd is very conservative.


JVM is designed for and alongside Java.

I will consider Kotlin outside Android, when it becomes relevant for JVM design, being taken into account by all major JVM implementations and JEP proposals, instead of something imposed by an OS vendor, stiffing Java support on purpose.

Guest languages always end up eventually going down their own path.

Not even C++ developed alongside C and UNIX, managed to take over UNIX clones, or industry standards for OS and graphics APIs.

Typescript relevance might wither away when JavaScript gains type annotations, it is after all only a nice linting tool.

Despite all WebAssembly craziness, JavaScript still rules the browser and edge gateways.

If that is irrational, oh well.


> If that is irrational, oh well.

It is and you are being very defensive here. Which suggests to me that this isn't the first time you've been challenged on this front.

Dismissing things as "guest" languages maybe steps over the advantages these languages bring. If you had some rational reasons I'd take you more seriously. But you clearly don't. Using big words like "industry standards" doesn't really add to the argument.

> I will consider Kotlin outside Android

Funnily enough the only place I don't use Kotlin is Android. I never did much Android development. I've been using it since 2017 for server side development and the last five years also for browser development (via kotlin-js). It's actually replaced typescript for me. I do a lot of Kotlin multiplatform at this point. I don't recommend this to everyone. But it does work quite well for me as a better Typescript. It still cross compiles to Javascript of course. And lately to WASM if you want to. But the point is, Kotlin is not just a JVM language anymore. People do IOS native development with Kotlin now. With bi-directional swift integration, native libraries, and all the rest.

What things are for and aren't is mostly a mental block on your side. C++ and Typescript are widely used at this point.

> might wither away when JavaScript gains type annotations

If that's so beneficial, you could have been using Typescript for the last ten years.

Why did you waste ten years?


Big words matter, because there is a whole list of megacorps that rather keep using Java alongside C and C++ to implement their JVMs.

If Kotlin is so great where is the KVM taking over the world, outside ART, when no one is forcing its adoption like on Android?

Actually, is Kotlin Native finally good enough for JetBrains to implement a KVM, without having to rely in something writen in Java with all the related flaws?

I use Typescript where it is imposed upon myself, like Angular and Next.js, when I can have my way of Web development, it is plain Spring MVC or ASP.NET MVC with vanilajs.


> It is and you are being very defensive here.

Yeah, but you started it with

>> Mostly for irrational reasons IMHO.

Leading your argument with the sentiment that "detractors are just delusional" isn't going to lead to productive responses.

You can't very well complain that someone is defending when you initiated the attack.


My day to day JVM guest language is two decades old at this point and it is remarkably similar to Java and yet none of the latest Java releases have done anything remotely interesting enough that they would make me go back to Java ever.


And it is slow as always, assuming you mean Groovy.


I think languages that take C++ interop seriously will win over the long term. And that means I'm saying Swift is a better bet than Rust long term. So yeah.


The problem is that it is too Apple centric.

I have no doubts that is what will happen on Apple world, outside I am not so certain.


How so? Maybe 5 years ago that would be the case but they've been steadily making it cross platform and it's a great choice now for CLI's, servers, embedded etc.


OK, so lets go read about some basic stuff I'd want to do in Swift, I want to open some files, I guess that'll be part of the standard library

"Documentation for the standard library is presently hosted on the Apple Developer website"

That's not a great sign but sure this "cross platform" software is "presently" on the company website of the obvious real owner maybe that'll get fixed in the next ten or fifty years, I'm sure it won't affect the actual documentation right?

OK, so the feature I need works on tvOS 14.0 and watchOS 7.0 - but what about Windows? That's not mentioned because this is an Apple website and so it only documents Apple products.

Case closed.

As with Go, basically every other system is just a thin attempt to emulate the system they actually want you to use and where that's impossible too bad. If you're an Apple-first developer this is probably fine. What do you mean Windows doesn't have the user-group-other permission model? Just fudge it.


The lack of windows support is a feature, not a flaw :D


Just like Objective-C is a great choice for a GNUStep based distro, since 2000's.

We have been here before.

The investment of Apple into a cross platform Swift ecosystem is a fraction of what Microsoft is doing with .NET, and even it isn't without issues.

Outside Apple ecosystems there are much more mature options for CLI and servers software.


Yes there are more mature choices now, but Apple is serious about making Swift a c++ replacement and if they do that well, it actually has a chance of being a One Language To Rule Them All. Rust is too low level for people to use for Applications, servers etc, which is where Swift shines, and Apple is proving that Swift is viable as a systems language too.


I agree with all of that, I just don't believe it will matter outside Apple's ecosystem.

Developers on Apple ecosystem are the ones that would be using Swift like that, as it also provides a good to share code between apps and server side code.

Most likely Apple will also be the only one writing firmware or OS drivers in Swift, that is where Embedded Swift project started.


Unless Rust adds Swift-like C++ interop, which is a real possibility.


This has been recognised as the next important milestone for Rust and there's work towards making it happen. The details are uncertain yet, because move constructors are a big change for Rust (it promised that address of owned objects is meaningless, and they can be simply memcpy'd to a new address).


The Rust folks want a more usable Pin<> facility for reasons independent of C++ support (it matters for the async ecosystem) and Pin allows objects to keep their addresses once pinned.


Uhhhh no. Maybe if you only run on macOS then I guess? But as someone who ships on Windows, Android, Linux, and macOS (in that order) the probability of me adopting Swift for literally anything is… less than zero?


My observation is most people who suggest Rust alternative don't use Rust. People who actually use Rust known it is worth to rewrite C/C++ software in Rust, either the whole or part by part. There is a tool to convert C source into Rust too so you can retain the whole functionalities while migrating to Rust. I have done this with Lua and it work wonderfully.

The good news is Linux now adopt Rust. In the end it will be all Rust although it may take a long time to migrate from C.


> My observation is most people who suggest Rust alternative don't use Rust.

This is a very condescending statement. In fact, for most software, when given the option of a full rewrite from C/C++ to another language, Rust is usually the least reasonable option. Fully automatic memory-managed languages should be considered first.

> People who actually use Rust known it is worth to rewrite C/C++ software in Rust, either the whole or part by part.

A full rewrite is not a feasible option for many large projects, and Rust does not make it easy to rewrite C++ code piece by piece, as the linked article clearly explains.

It's not true that developers don't like full rewrites. Most often, it's the path most developers would choose if they had enough time and funding. But in reality, you don't get either of those two.

And even if you are willing to do a full rewrite, your project probably has non-trivial dependencies on large, mature C++ libraries. You are not going to rewrite those. This is why more new projects are started in C++ every day than in Rust.


> Rust is usually the least reasonable option

If the software was originally written in C/C++ based on some performance reasons (avoiding GC/being in control of boxing/being in control of when to use vtables etc.) then what would be more reasonable options?

> Fully automatic memory-managed languages should be considered first.

Those languages have existed for 20+ years so if they were ruled out as part of the original decision making then they probably still aren't applicable.


Problem was that 20 years ago some of those languages didn't had AOT compilation options, or if they did, they were commercial, priced at ways most developers would rather not bother.

Plenty of software has been written in C or C++, only because they were the only compiled languages known to the authors.

Having said this, Go, D, Swift, OCaml, Haskell, Common Lisp, C#, F#, Java (with GraalVM, OpenJ9).

All of them offer ways to do AOT compilation and use value types, granted Java is too verbose using Panama for that, and one is better of choosing one of the others.


I've been using F# and there are actually several roadblocks for AOT F# [0]. However, a self-contained .NET JIT executable is still surprisingly small (18 MB for an ASP.NET minimal API written in F#), easy to build, and easy to deploy.

[0] https://github.com/dotnet/fsharp/issues/13398


Yeah, I listed it, because it is kind of possible, even if there are issues currently.


And even if the speed and memory penalties are exactly the same as they were 20 years ago, you no longer need to support a pentium 3 with 64MB of RAM. If you write code that would have performed well 20 years ago, then bloat it 300%, it'll run just fine. I'd rather have that than just about any electron app.


In fact, in what concerns most of the languages, they scale down to computers much weaker than most of my 1990's PC desktops.

Some examples, one per language, there are others I could list.

https://www.wildernesslabs.co/

https://tinygo.org/

https://www.ptc.com/en/products/developer-tools/perc

https://www.swift.org/get-started/embedded/

https://wiki.dlang.org/Programming_in_D_tutorial_on_Embedded...


> Those languages have existed for 20+ years so if they were ruled out as part of the original decision making then they probably still aren't applicable.

There are huge C++ code bases that are 15+ years old and are still actively maintained because the cost of a rewrite is too high for something that still solves the problem well enough.

Most of the large C++ projects I've worked on were written in C++ because it was the most common and mainstream language given the CPU and memory constraints of that time. We have significantly more powerful CPUs now, especially considering multicore computing, and easily 5-10x more RAM than 15 years ago. Java/Kotlin, C#, Go, TypeScript, Swift etc., are perfectly applicable to many more problem domains where C++ once dominated. I can easily agree that many C++ projects would be better off transitioning to a fully garbage-collected language than to Rust.


> Those languages have existed for 20+ years so if they were ruled out as part of the original decision making then they probably still aren't applicable.

They were ruled out when the RAM/CPU budget per $SERVER could have been an expensive 4GB/2-core for a complex server processing transactions in real-time.

Today, that same complex server can cheaply run on a 48GB/6-cpu server. Those performance constraints for exactly the same $FUNCTIONALITY are such a low hurdle, dollar-wise, that it makes no sense in most applications of this heuristic.


> Fully automatic memory-managed languages should be considered first.

Of which none has solved concurrency. Some like Java prevents UB but garbage data will still be produced if you don’t diligently protect the access of the shared data.


Java doesn't produce 'garbage data', racing writes will never show intermediary results.


Loss of Sequential Consistency means realistically humans cannot understand the behaviour of the software and so "garbage" seems like a reasonable characterisation of the results. It might take a team of experts some considerable time to explain why your software did whatever it did, or you can say "that's garbage" and try to fix the problem without that understanding of the results.

The hope when Java developed this memory model was that loss of SC is something humans can cope with, it was not, the behaviour is too strange.


Even with sequential consistency, interweaving multiple threads produces results that go firmly into the garbage category. Even something as simple as adding to a variable can fail.

To solve interweaving, add mutexes. And once you have mutexes you'll be protected from weak memory models.


What is the end result of two threads adding +1 to the same counter 1 million times each in parallel?

Well, the result is safe but unknowable. I would call that garbage data.


> Fully automatic memory-managed languages should be considered first.

Why? If it was written in C++, there's a good chance it was so for performance reasons. You wouldn't want to throw that away with a GC.


> If it was written in C++, there's a good chance it was so for performance reasons.

I agree. But imagine that games like Doom or Quake would have been unthinkable if they weren't fully written in C/C++. Now, however, we have 3D game engines like Unity that expose a C# API for game logic scripting, and it seems to work just fine. Performance is becoming less of a concern for more and more problem domains.


With lots of Assembly, inline Assembly isn't C or C++, regardless of how many devs might pretend otherwise.

It is like saying C libraries are Python, only because they happen to be used from Python bindings.


If you want assembler Rust seems like a smarter choice because in Rust that's just part of the language whereas in C or C++ it's a vendor extension.


Assembly is never really part of the language, at most one could consider the syntax to inject a stream of opcodes being part of the language.

Both of us are old enough to remember when any useful compiled language used to allow for inline Assembly, extension or not.


True, but I would guess that projects more susceptible to rewrites would be low-level core libraries where state-of-the-art performance is always desirable.


Correct. And if those projects exposed a C++ API, then rewriting them in Rust would be highly problematic, because Rust did not prioritize C++/Rust interoperability (for well-understood reasons). So, you can either have a C API and move to Rust or have a C++ API and create a Rust version of the library for Rust developers, but your original users of the C++ library will stick with the C++ version.


You can use C++ libraries from Rust. That's a very normal thing to do. People start new projects in C++ either because they themselves don't want to learn a new thing or because they don't want their employees spending time learning a new thing.


Appart from cxx.rs. I think most binding between C++ and Rust are in fact C and Rust binding. So you need a C API to your C++ library (no template, no std etc...). So for me you can't use C++ library from Rust.


You can just use CXX? Idk what to tell you. A coworker of mine is doing it. It's not some kind of weird thing.


cxx only support a part of c++ STL container. It doesn't support template and custom container implementation. So no generic, no variadic number of argument, no automatic type déduction etc...


> You can use C++ libraries from Rust.

I doubt it. You can use C libraries from Rust, and emit C libraries in C++.

> because they themselves don't want to learn a new thing or because they don't want their employees spending time learning a new thing.

Whining about others not wanting to learn when you could have learned how Rust FFI works is, really, hilarious :-)


A coworker of mine is using CXX in a combined Rust and C++ code base. This is not exotic.


In my experience, rewriting C++ into Rust is non-trivial because idiomatic C++ expresses things that Rust cannot. This impedance mismatch breaks architecture, and that often isn’t allowed in a rewrite. I’ve seen multiple C++ rewrite attempts fail because of poor interoperability with Rust’s constraints. Language interoperability that is high quality and low friction matters to people, and in the case of C++ that is decidedly challenging.

My view at this point is that you are better off starting from a clean sheet of paper in Rust than trying to make Rust do C++ things it was not designed to do.

In the specific narrow case of performance-engineered code, Rust also seems to consistently produce slower code in my experience for myriad weird reasons, it isn’t one thing. In many cases I don’t even think it is the fault of the language per se, just a side effect of other factors. Nonetheless, customers don’t care about any of that, they won’t accept a performance regression just because you rewrote it.


Idiomatic "modern C++" as defined by the Core C++ Guidelines is very similar to Rust, it even has its own bespoke ownership+lifetime checking mechanism.


Do you know if any big public projects using the GSL or similar? I haven’t found any but I’d like to check them out.


Carbon is made for companies like Google with millions of lines of C++ using very C++ interfaces. They can't incrementally rewrite without refactoring everything to C-style headers, and that would probably involve a ton of void-pointer nonsense if its even possible.


> millions

s/m/b/ too


Carbon devs explicitly say use Rust if you can.

Non-trivial C++ programs depend on OOP design patterns, webs of shared-mutable objects, and other features which Rust doesn't want to support (Rust's safety also comes from not having certain features that defeat static analysis).

Rust really needs things written the Rust way. It's usually easier with C, because it won't have clever templates and deep inheritance hierarchies.

Even if your goal is to move to Rust, it may make sense to start with Carbon or Circle to refactor the code first to have more immutability and tree-like data flow.


> I have done this with Lua

Do you by chance work at Cloudflare, who has migrated away from Lua to Rust?

Curious to hear observations on productivity hit going from Lua to Rust.


In Cloudflare's case, Rust is much more productive.

Rust modules can handle any traffic themselves, instead of a split between native code and Lua that is too slow to do more than config (Lua is relatively fast for a scripting language, but on the critical path it was a "peanut butter" slowdown adding latency).

At the size and complexity of a server serving 20% of the Web, Lua's dynamic typing was scary. Modules in Rust can enforce many more requirements.

Rust's solid dependency management also helps share implementations and config logic across modules and even different products, instead of everything having to go literally through the same server.

https://blog.cloudflare.com/20-percent-internet-upgrade/


> instead of a split between native code and Lua that is too slow to do more than config

In case you’re not aware, Cloudflare ran on LuaJIT (not just for config) until not that long ago.

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


Five years ago is a pretty long time, and kornel does (or did) work at Cloudflare.


My observation is most people who mix up C and C++ use neither. How could you even automatically migrate when a lot of things you do in C++ are straight up illegal. Not to mention relying on third-party software like Qt.


It really hate libraries that call themselves C++ libraries, when they effectively are written in the common subset, with extern "C++" for C++ users.

Technically correct by ISO C++, in practice that isn't the way to write modern code.


Linux is only adopt Rust for device drivers and selective subsystems. I am not sure if it is a wide-adoption.


There are Linux targets which don't have Rust. So the drivers rule is because if we make the mm subsystem depend on Rust then a dusty architecture with no Rust can't run Linux any more. This is tolerable for userspace, realistically your Python document mangling code probably does not in fact need to work properly on a machine nobody has manufactured since the 1980s - but not acceptable to Linus Torvalds.

The expectation is that over the next say, decade, Rust gets more trusted by Linux maintainers and perhaps grows more platform support e.g. via the GNU Compiler Collection, and simultaneously some of the dustier platforms "rust out" of Linux because the few maintainers stop caring about new Linux versions. So one day you can rewrite core subsystems in Rust if that makes sense.


> The thing is, there is a lot of existing software in the world written in C and C++.

This is true, and I think that there is a type of language that I don't think have been explored yet: Cross language ABI language.

That is, the language is fully designed for being the glue between multiple languages to allow for migration in the future. I think it would probably end up being C.

> There are several languages that have managed a transition away from a base language into a more capable, flexible successor language, though: TypeScript is an evolution of JavaScript, Swift is an evolution of Objective-C, and C++ itself is an evolution of C.

And yet none of these have fully escaped the chain of their predecessors. And that is almost the point, people actually wanted to do what JavaScript could do, what C could do, what Objective-C could do. Then we put cover on it, but it is still a wooden table at the end of the day.

Have Hyrum's Law teach us nothing? Unless you consciously make the effort to REMOVE features, it will always be there. The fact that cross language boundary is complicated is a sign that the new language is actually shedding off technical debts. If I wrote a massively complicated function in C that leaks file handles, the answer isn't to read /proc/fd before and after, then manually unlink the new FDs. The answer is to actually dig through the code or rewrite it.


> That is, the language is fully designed for being the glue between multiple languages to allow for migration in the future. I think it would probably end up being C.

Unfortunately, C is woefully insufficient for such a language. At a minimum, you'd want to have a language that can distinguish between nullable and nonnullable pointers, pointer-with-array-len (so C++'s std::span or Rust's slice), and read-only versus read-write pointers (which const only kind of does). Expressing no-alias relationships and very basic lifetime relationships is also pretty critical for several languages. Multiple return values is something I'd love to see, in addition a success-object-or-error-object (something like a Result type). Having a dedicated not-necessarily-null-terminated UTF-8 string type is also useful.


While raw C is not super helpful for generating nice bindings, I think you could get most of the way there if there were annotations for everything, e.g. like how the __counted_by__ attribute was added.


The problem with almost all of those is that most languages won't support it; that's a FFI specific to Rust.

I mean, what do you do with those languages that don't have the concept of lifetime relationships, like Python? Or those in which read/write pointers make no sense (Tcl)? How about languages with linear datatypes? Or languages that don't allow self-referential data structures (like Rust)?

The only practical approach is to have an interface that is the lowest common denominator of most languages, which is what we already have with C.

I did work in CORBA in the 90s (and someone else mentions COM down below, which I also worked a little with), and the way I'd go about it[1] is similar to swig but in a CORBA/COM type fashion - an IDL that will generate bindings for specific languages. This requires quite a lot of prescient thinking - after all, lifetime ownership is a fairly new thing, so who knows what new requirement will come in the future?

In some future language, you may want FFI to encompass closures, in which case you'd have extra syntax for capture by value vs capture by reference, and you may not necessarily want ownership change in the function call (for example on a single-threaded callback function, the value captured by reference is safe for either party to modify).

Nail down the data interface and you're 80% there.

======================

[1] The best way to go about it would be using something like s-expressions: allow some basic execution to encompass every type of object a language might ever need.


As hairy as it is, COM is an example of a cross language API/ABI. It's workable from C, C++, C# etc etc and even accessible in MacOS as "NSPlugin".


Also the design macOS drivers use.

However on Windows, given its prevalence, especially since Vista, one would expect that by now Windows team would have bothered to make it less hairy, but elas it has never been a priority, when when they actually did something (WinRT) is was woefully mismanaged and now no one cares.


>As hairy as it is, COM is an example of a cross language API/ABI

I think the reverse will also be true. Any cross language API will get issues.


Indeed, example all the languages that target JVM, CLR and WebAssembly, and the missing bits between what the platform can do, what the "systems" language exposes, and what everyone else is able to expose or consume.


The answer is obviously to have a background task that periodically frees the leaked handles made by a program written in Carbon using a c library.


> In short, Carbon is a project to create an alternative front-end for C++

Well this was a shocker, to say the least! Why would you intentionally pick the same name as the transitionary gui framework from macos classic to macosx when the demographic you're targeting is the most likely to confuse the two terms?


How often do you, in all seriousness, reference the transitory UI framework that was introduced two decades ago and deprecated over a decade ago?

At some point, it's okay to reuse names.


Sure it's ok to reuse names, but why would you want to opt into such confusion? It's jot so much that someone is seriously going to be confused so much as just bad branding. You could pick any name.


There is no realistic confusion. Heck, I wrote code in that Carbon back in the day and the association never even crossed my mind. Many professional developers weren’t even adults yet when that Carbon was sunset, or weren’t involved in the Apple ecosystem.


The Apple tunnel vision is pernicious here on HN. Ill tidings for American tech if people can't see the forest through the trees...


Also last I heard Carbon was a temporary codename that they were going to replace with something else if/when the language ever became production ready, though I don't know whether that's still the plan.


I haven’t heard this, and with the number of conference talks and media done about it, if that were the plan I’d expect it to be pretty front and center so that those interested would be aware.




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

Search: