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

I don’t think Rust syntax and patterns (no classes) are especially elegant for many tasks. I can’t express the behavior of a system as cleanly in Rust as TypeScript, C#, go or Python. I know that’s not what it was designed for, but a guy can dream.

But what Rust has is the best tooling bar none(cargo, build system, compile time checks, ease of first use). The tooling is actually more important than the borrow checker and memory safety in my opinion.

If I clone a Rust repo, it’s actually easier to compile, test, and run the code than any other language. It avoided the fragmentation of JS/TS (npm, yarn, pnpm, bun, deno) and dep hell of Python (which was a nightmare until uv).

If Rust didn’t have the syntax warts (macros), it would be eating the world.



This is a bizarre take to me, what do you want to do with classes that aren't supported by structs and traits? Imo the usability issues with rust arise from the borrow checker and associated complexity + restrictions on patterns, so I'm surprised that you're citing macros and classes.


Access control.

Here's a struct that maintains an invariant - say, that field a is less than field b. That invariant should be set when it is created.

You find a bug where a is greater than b. Where is the bug? With a struct, it can be anywhere in the code - any line that touches the struct. But with a (well designed) class, a and b are private, and so you only have to look at lines of code within the class. The surface area where the bug can be is much smaller.

The bigger the code base and the more well-used the class is, the more this matters.


Rust has privacy and encapsulation just fine. More than that, Rust's entire safety story is built on these mechanisms; being unable to (safely) access private fields outside of the module in which they were defined is load-bearing when it comes to safely encapsulating unsafe code.


You can do exactly this in rust using non public fields and accessor methods.


I think the large C++ or Java shaped hole in your understanding is simply that you think "class" means encapsulated and "struct" means Plain Old Data and in Rust that's not what it means.

Take std::os::fs::OwnedFd the file descriptor. In fact of course this struct is literally just a C-style integer inside, it's the same size in memory, representationally they're identical. But, it's encapsulated, so it gets to enforce the fact that file descriptors are never -1 by definition, and since it is encapsulated it gets to refuse to participate in arithmetic, and to call close when we throw away the file descriptor, and so on. It's a huge improvement.


Ah, that makes some sense, although some reading says that struct member visibility is by default the module, which is a file if you don't do anything. If you wanted you could probably just wrap all the structs you want to be protected inside a module per file? It is a bit annoying though. I guess the issue here is that in rust struct fields need to be accessed for trait implementations. It wouldn't be backwards compatible obviously, but I wonder if they could have tightened that so that by default only trait implementations for a struct can access that structs members?


Rust has exactly that. The difference is that rust considers the scope of private access te be the entire file it's defined in, not just its methods.


Just the module the struct is defined in, not the file. Easy mistake to make, given that a file is implicitly its own module, but you can create submodules within a file with the `mod` keyword.


I thought it crossed into submodules as well, making it the entire file?


Rust has access control, and rust has better mutability and reference control. Many languages like C# and Java let you take references willy nilly and do almost whatever you want.


Rust has access control. Fields are private by default.


I'm confused too! When I write Python, I do it in a similar style as rust, but knowing the classes and enums are sloppier than rust's; regarding mutation for example.


>dep hell

As a C programmer, i'm always a little panic how a small Rust Program can pull in that many crates when compiling.


Once you understand that a crate is the translation unit in Rust, it doesn't feel as bad. Most medium to large Rust project's will separate out their code into separate crates for both organization and compile time.

I've definitely cloned down my fair share of C projects, mashed the make command into my terminal, and watched the gcc/clang logs fly by and never batted an eye beyond checking the sha256sum on any downloaded tarballs.

There's a valid argument to be made about supply chain attacks, but there does exist tooling to lock that down, and I would argue that any serious software development firm should be auditing every third party dependency they take on.


> If I clone a Rust repo, it’s actually easier to compile, test, and run the code than any other language

zig is very comparable, and much faster at doing so. zig also comes with a build system, libc and can compile c programs. its a better c compiler and build system than most, lol.


But Zig doesn't have the very sophisticated type system that Rust has. Nor does it, importantly to DARPA, have the memory safety that Rust does.


A type system in programming languages is a way to express and enforce compile time constraints (conventionally, anyway).

zig's type system is pretty straightforward, but its comptime is very powerful and, among other things, can enforce arbitrary compile time constraints. It's not the same as rust's types, but I wonder if it isn't better in many ways.


It's not comparable, comptime is more of an alternative to macros. You can build complex systems with it, but they don't natively give you the algebraic reasoning abilities that the typechecker does, at best you'd have to reimplement it yourself in an ad hoc way. Rust's proc macros are also fully programmable and have comparable expressive power to comptime.


I used Zig in the past (after my "why don't we just write everything simply in C" phase). I don't think I used comptime too much, but I understood why it would be useful.

Now I write Rust and absolutely love it, except for the damn macro edge cases, like not being able to use a known-at-compile-time string for format!() unless it's a literal (I even tried to fake it with more macros, no dice). I think Zig's Andrew Kelley mentioned this exact scenario, if I recall correctly.

It's funny because I do write a lot of code that generates code, but I avoid macros if I can.


Don’t underestimate Zig’s comptime or modern C++’s constexpr. You can use these to prove things about the program at compile-time far beyond the type system. In recent versions of C++, the scope of code that is compile-time verifiable is quite large, nothing like when it was first introduced 15 years ago.

This has limited (but not zero) applicability to memory safety but it has a lot of applicability to many other classes of defect against which Rust offers no special protection. Features like this are why modern C++ is still the language of choice for new software in high-assurance environments at DoD when performance matters. (When performance doesn’t matter it seems to be Java and C#.) These systems often have little or no legacy C++ code as a dependency, so that isn’t a factor.

I have less experience with Zig but this is an area where Rust can’t replicate the safety features of modern C++. With the introduction of compile-time reflection in C++26, this gap will increase. People who aren’t deep in it seriously underestimate what can be verified at compile-time in recent versions of C++ without the use of ugly arcana (which used to be required).


C++ constexpr is a nasty trap. Because after all it says right on the tin that we're getting a constant expression right? So it's as powerful as Rust's const right?

Nope - of course the usual suspects insisted they needed a way to write non-constant expressions and have that somehow "work" anyway. So whereas a const function in Rust genuinely is constant, a constexpr function in C++ might not be, and we only find out whether it was if we force the compiler to do the operation at compile time. If we leave any gap where it can just delay until runtime that's what happens.

You can literally write a random number generator, label it "constexpr" and a modern C++ compiler goes OK, that's not actually constant, but you didn't technically promise it was constant you just used this useless "constexpr" keyword to gesture performatively at the idea of compile time evaluation without promising anything so we'll only complain if you try to use it in a context where I must know the concrete value at compile time.


True, however I would expect that anyone that knows constexpr is also aware of constinit, consteval and static constexpr.

Does it suck instead of having a single mechanism?

Yes, but the tools are there to actually enforce it at compile time.


These are honest questions and not rhetorical: how does Zig handle versions with syntax changes or breaking changes?

Can you mix Zig libraries written X years ago with modern Zig? Will today's code work in 5-10 years if I want to use it in a project then?


Zig has not hit 1.0 yet, and as recently as a few months ago completely reworked how every form of IO is written. AFAIK, this wasn't a syntax change, but it changed the function signature or type definition of every piece of code that reads/writes a file, establishes a connection, etc. At the current time, there is little guarantee that the code you write today will still work in 5-10 years time.


Thanks for the info, I was hoping there was something like Rust's editions that would allow for mixing libraries with differing language versions that have breaking changes.


> It avoided the fragmentation of JS/TS (npm, yarn, pnpm, bun, deno)

just use npm, the others are just more options, thersr is no "fragmentation"


Not everyone likes OOP you know? Some people love low abstraction code.


> If I clone a Rust repo, it’s actually easier to compile, test, and run the code than any other language.

I beg to differ because Go has a large standard library which means less dependencies than Rust on average.


It's not usually the standard library or dependencies that create the issues I've seen. The teams I work with producing Go tools (across multiple companies) invariably require carefully orchestrated dev environments that are nigh-unreproducible. It's 50/50 on whether I can actually build a random project first try without reading the instructions if CGO is involved, which seems to be all of them.

My experience with random rust projects is that they usually "just build", with limited exceptions like weird embedded stuff.


Rust projects which depend on C libs have very similar issues.


Well yeah, because C has those issues. People like to clown on the Rewrite It In Rust attitude, but it comes with real benefits.


I haven't experienced this. Rust's build system allows you to automate most of the pain in building/bundling those dependencies, so it's just up to the builder to have the right headers (if they're not bundled). That makes it no worse than meson C/C++ builds.

In Go, it doesn't have any of that so it depends on the end builder of the binary to be aware of all the C dependencies and manually manage integrating the cgo configuration into their build process.


Its highly dependent on the kind of project. A few years back libxml and libxmlsec1 were a consistent pain in the neck for me. I don't know about now, I simply moved on from the project that needed me to interact with them.


I don’t hate the C language. I hate the C compiler (and the rest of the toolchain). Anything that helps me not interact with the C compiler is a huge win.


I worked for 10 years with Go and almost never seen a cgo dependcy, it's far more common in Rust, it's not even comparable. Rust replaces tons of c/c++ so it has more ffi.

The vast majority of Go code, like 99% doesn't have a single cgo dependency.


Again, I disagree. CGO is rarely needed for Go projects.

And is actively discouraged by the community.


Don't know what to tell you, it's just my experience. I see stuff like this:

https://github.com/discord/lilliput/blob/master/cgo.go

far more commonly in corporate Go code than Rust.


You're showing a repo wich has more cpp code than Go what's your point exactly?


The entire point was within the file they posted.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

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

Search: