Skip to content(if available)orjump to list(if available)

The Core of Rust

The Core of Rust

76 comments

·August 21, 2025

khuey

Ironically the "simple" JS program has a bug in it. The documentation for fs.watch is very explicit that the filename in the callback can be null and that you need to check for that. In Rust that fact would be encoded in the type system and the programmer would be forced to handle it, but in JS it's easier to just write bad code.

https://nodejs.org/api/fs.html#filename-argument

Waterluvian

Typescript would require you to check for null before use, which I think makes this a good example of how TS is oftentimes a fairly gentle step up from JS. Or, at least, closer to the correctness of Rust without all the heavy stuff.

quotemstr

But you don't get manual memory management then. No GC, safety, and simplicity: pick any two

koakuma-chan

Do you manually manage memory in Rust? Because I just write Vec::new or vec![], just like how I would write new ArrayList in Java.

ori_b

Sure, but GC's not the only upside.

Waterluvian

That’s true, two different tools have different pros and cons.

TylerE

For a large number of people including myself, manual memory management is a huge con, not a pro.

marcianx

There are further bugs:

`for path in paths`

should be

`for (const path of paths)`

JS will immediately error on the lack of parens, but the `in` vs `of` iterates over indexes, not values, and those indexes are unfortunately converted to strings (since `for-in` is object field-name iteration). So even TypeScript would not have caught it when the (stringified) index is used as the first argument of `fs.watch()`.

sestep

True, but also the loop syntax is simply incorrect, which would have been caught by running it; so probably a better interpretation is simply that the author didn't spend much time thinking about that JavaScript code because it didn't matter for their point.

masklinn

> it didn't matter for their point.

Which is mostly a lie, since at least half the concepts they gripe about in rust are in the js snippet.

sestep

Yep fair. I'm not sure why they didn't spend more effort on the JS part, just saying they didn't.

kiitos

> Let’s look at a Rust program that does something non-trivial: ... (a bunch of highly specific explanations of deeply technical details from the very short program source code)

what does this program actually do?

all of this extraordinarily subtle analysis, about rust language specific properties, specific to this individual program, and no actual summary or description of what the program is supposed to do!

what it does is print out a line whenever a file, matching certain criteria, is modified. that's it.

and as such it's an almost pitch-perfect example of exactly what's difficult with rust as a language. what this program does is trivial to describe and should have a commensurately simple implementation. but rust makes the programmer care about a dozen? dozens? of details that have no relevance to the problem domain at hand.

for people who are just hungry for complexity this is an exciting challenge that they can tackle and solve! but that complexity, that challenge, is self-inflicted, almost always incidental and unnecessary work

tracker1

Anyone else get completely side tracked as soon as you saw the shebang (self-executing rust scripts)? MY mind kind of exploded in a similar fashion to when I discovered Go could do the same. It's definitely a nifty feature and can see it getting a lot of basic usage. I've seen a couple projects that do similar with rust to control build and testing pipelines, this could be a good alternative in those cases.

That said, I mostly just use Deno + TS for my shell script needs beyond simple bash. Mostly in that JS is hands down the language I know the best (28 years), close would be C# (24 years) for me. I was also an early adopter of Node. I also think that dealing with shared/centralized packages is an easier option for Deno than Node, Python or other languages/environments. The cargo front-matter here seems to work similarly.

tracker1

Just to add, I literally meant sidetracked... started searching for the "-Zscript" feature in cargo, apparently in progress since 2023 with an open issue that's close to complete. Along with looking back into ZomboDB's repo, where I saw Rust being used for the build pipeline stuff, not that I completely understand it in context.

Not to mention how useful the cargo front-matter handling is in terms of portability for these kinds of scripts... one file to share, and no extra "install/init" step to bring in dependencies (such as with say Python or Node.js).

TylerE

That’s just a basic Unix thing.

Any file starting #!/some/path just means for the shell to invoke that command and pass the contents of the file on stdin.

tracker1

I know this... my point was in that Rust didn't have this feature 5-8 years ago when I first started reading/learning about it. A lot of languages haven't had an active scripting-capable usage that can do this until fairly recently. C# even has it in .Net 10, though I'm not sure about dependency handling in that case.

I like and was commenting that rust has the cargo frontmatter instead of a separate cargo file, same for deno in that it can reference the repo/url directly instead of requiring a separate modules file/folder (like node package.json/node_modules) or even with python. You can reference the modules you need directly.

ameliaquining

A bunch of third-party Python package manager clients, most famously uv, support this now. They all use the same front-matter format (PEP 723). Unfortunately, pip (the first-party package manager client that's usually distributed with Python) doesn't support it yet: https://github.com/pypa/pip/issues/12891

ameliaquining

Most languages currently do not support this in a way that lets you specify dependencies from a package manager. And some don't support it at all; most C and C++ toolchains, for example, don't have a way to compile and run a single source file in a single command.

tracker1

Exactly, that alone makes it far more useful/portable in practice than a lot of other languages for this type of thing. A python file can have a shebang, but it'll need a bunch of other files around it for module references, etc. Not to mention initialization/setup, etc.

The fact that dependencies are referenced in the file and automatically handled at runtime (first or repeated) is a really nice feature to have... it's expressly why I started using Deno over other options for this.

koito17

Minor nitpick

  println can only print things that implement the traits Display or Debug. As a result, Paths cannot be printed directly.
Not all OSes store paths compatible with UTF-8. In Rust, all strings are UTF-8 encoded. Thus printing a Path is a lossy operation (i.e. cannot safely be round-tripped). Path exposes a `display` method returning a type that implements Display. This is a fact Rust is encoding in its type system, whereas in JavaScript (and TypeScript), it's not really possible to state "strings internally are UTF-16 and you may need to invoke TextEncoder / TextDecoder to safely deal with paths that are not Unicode". If you fetch from a server sending Shift_JIS text and invoke `response.text()`, you get an empty string at runtime (in my experience). If you aren't experienced in dealing with text encoding issues, I can see this becoming a lengthy debugging session.

As others have noted, the JavaScript program has a bug not present in the Rust program, and a syntax error (should probably use for..of, not for..in). The example definitely uses more concepts than "first-class functions". You still have to understand iterators, just like in Rust, and it uses CommonJS instead of ES Modules, but I digress. The usage of async/await and Promises is another concept to teach, and the usage of top-level await is specifically something that wasn't supported in some runtimes (e.g. Node) until recently. It still isn't supported in the latest version of some mainstream JS engines (e.g. Hermes, which is used in React Native)

stouset

To your above point about paths, it’s things like this that keep me coming back to Rust. This was just one example, but other languages are absolutely littered with pitfalls and gotchas that—individually—aren’t all that likely to happen.

But all of them? Over a given program’s lifetime? In aggregate these end up being responsible for an absolutely wild number of random bugs that crop up in your exception logs that need to get tracked down. And it never ends. There are an infinite number of edge cases you’ve never thought about that aren’t fully handled and that some of which are constantly being tripped.

This just… doesn’t happen in Rust. The type system catches (and/or completely rules out) a ridiculous number of these situations. I have repeatedly written finished software in Rust, where once it was released there was only an occasional need to add features but the typical bug-squashing treadmill just doesn’t exist.

That’s not to say there are never bugs. You can express faulty logic in any language. But the number of stupid impedance matches that are categorically ruled out makes the experience of operating and maintaining Rust program once written a widely different experience than I’ve had with any other language.

tracker1

I find that understanding thenables/Promises and async-await in JS/TS is emphatically not something a lot of devs really understand. It really shows when you see something like...

    var fn = async (param) => new Promise((res, rej) => {
      ...
      fooLibraryCall(param).then(res).catch(rej);
    });
I've literally seen similar to this... where devs see wrappers for the callback syntax, then apply the same to thenables and use manual Promises inside an async labelled function. It makes my mind bleed to see it, and I've seen it a few places.

Then, of course, there's dealing with module imports and async import() methods and how they operate or get transpiled or split, etc.

tomjakubowski

Sometimes you still need to work with promises even inside an async context. Imagine an async function which needs to `await Promise.all([...])`. In this case, `then()` can be a useful tool to make new promises from an async call.

tracker1

Of course.. I was referring to having an async function, but having it create a "new Promise" that in and of itself is just calling a method that already returns a promise... it's creating extra closures and overhead that aren't necessary at all.

Sometimes I'll add a `.catch(() => null)` or similar for manipulating a specific call with `.then`, if I want to manipulate something out of flow. Such as a convenience method to normalize api fetch calls, etc. That's just useful functionality, not making literally wrappers for no benefit or reason.

null

[deleted]

petcat

I often encounter people that want to learn a programming language and ask if they should pick Rust as their first language. My answer is universally: NO.

Learning a first programming language is hard. And Rust will only make it harder since all you're going to do is debug compiler errors all day and never even see your program actually run until it's "perfect". This will be incredibly frustrating and you'll give up.

I always tell people to start with Python, JavaScript, or Lua. You can make something fun and interesting for yourself, like a game, and get immediate feedback and you can iterate quickly.

tracker1

I would suggest Python or Lua before JS if you want to learn formally, such as following a book/series/class. JS (and TS) just have so much flexibility and many functionalities have been enhanced over the years that depend on the runtime context and build tooling in some cases.

Don't get me wrong, I love JS/TS since before the "Good Parts" book ever came out. The only advantage it has as a first language is you can start tinkering directly in the browser... Which is something I use to this day... the debug console in the browser, I can exercise a generated API client before the UI features are flushed out.

If you want to learn with the intent of "I want to build $THING." then JS/TS is probably a great language to start with... you will probably want to read something like a for dummies book to start, then bootstrap with a coding ai... and tinker until it works. Note: don't do this for anything security critical when starting out.

baq

I agree.

Rust wouldn't be a bad language if humans were able to take it in all at once. The problem is, nobody learns like that and Rust is very hard to iterate on if you don't know a lot of the key concepts.

The problem with this is you'll necessarily have to unlearn something or be frustrated when you achieve some level of proficiency in other languages since it still requires all those concepts which don't exist anywhere else.

zozbot234

There is an easy subset of Rust, namely the "pure functional" subset that doesn't use reference types at all and just passes everything by value. The use of & ("shared") references is only marginally harder. All of these features can be introduced step-by-step, together with basic notions that are not exclusive to any programming language. I'm aware that this is not how Rust is generally taught, but it's worthwhile to attempt such an approach.

tucnak

To be fair, Rust is genuinely just as _hard_ in 10th language capacity.

metaltyphoon

Nah not really. If you are in C/C++ land you know exactly what problem Rust solves. If you only even known GC languages then yeah it will be a up battle hill.

stouset

I really don’t think so, but it probably depends on which languages you’ve used in your life.

I’ve spent most of my time in C, Ruby, and spend most of my time dabbling around in functional languages. All of the core bits of Rust from this post more or less clicked immediately for me. The other features are there, but they’re typically not something you need to internalize to comprehend Rust as a whole.

The biggest hurdle—as for most people—was learning what the borrow checker is really trying to teach you about the structure of your programs and internalizing those lessons. But having some experience with RAII and good practices around manual pointer ownership in C helped pave a pathway toward understanding those concepts.

sarmadgulzar

I know I'm biased, but Rust is the closest thing we have to a perfect programming language. Is the borrow checker a pain in the ass? Yeah. But is it necessary? Absolutely. Imagine writing the same buggy program in C, deploying it, and then it blows up at runtime—you still have to fix it, right? A bug is a bug, and it needs fixing. The difference is Rust forces you to deal with it before you even get a binary, while with C you might get a 3 a.m. wake-up call trying to figure out what went wrong. So it’s not that Rust is harder, it’s just different. It takes a paradigm shift in how we think about writing safe and secure code. Change is uncomfortable in general for humans and that paradigm shift is precisely why most (I hope not) people feel this way about Rust.

tucnak

> Is the borrow checker a pain in the ass? Yeah. But is it necessary?

You've missed the primary point of the post entirely. Borrow checker per se is not the problem; it's the sheer amount of everything. There's multiple ideas of perfection. Those of us to have very much enjoyed ostensibly imperfect Rust of 2018 find this particular, current flavour unappealing. It may as well be capable tool in deft hand, however, as-is the case with everything in life, you cannot help but ask yourself THE question; is it worth my effort? For me personally, if I were looking for better C/C++ in 2025, I would choose Zig before Rust any day of the week (one exception being Postgres stuff, pgrx ecosystem that is really special!)

But then again, anything beats writing C for a living.

IshKebab

The closest thing I've seen to "simple Rust" I've seen is Gleam: https://tour.gleam.run/

It's clearly very heavily inspired by Rust.

akkad33

> It's clearly very heavily inspired by Rust

The creator has said it's not. It's compiler is in rust though. But Gleam is an entirety different language in terms of paradigms and target runtimes. It can't really replace rust

IshKebab

> The creator has said it's not.

Well that seems highly unlikely given the huge number of similarities.

ameliaquining

Which similarities are these, that numerous other languages don't also have?

veidelis

Can one do 3D in Gleam?

raphinou

I encourage you to take a look at fsharp if interested in another 'simple rust'

hedgehog

Having written a moderate amount of both Rust and TypeScript they seem different but I wouldn't say projects in one are significantly simpler than projects in the other. Rust itself feels a little more complicated than TypeScript, but more carefully thought out. TypeScript has more cruft and legacy footguns. Rust tooling is much better (and faster). For cranking out web front end code TypeScript will get the job done faster, most other needs I run into are easier solved using either Rust or Python when starting fresh is an option.

null

[deleted]

nromiun

> There’s a famous quote by Bjarne Strousup that goes “Within C++, there is a much smaller and cleaner language struggling to get out.” Within Rust, too, there is a much smaller and cleaner language struggling to get out: one with a clear vision, goals, focus. One that is coherent, because its features cohere. This post is about that language.

The problem is that using this "core" of a language never works. Either you need a feature or a library that touch the bad parts you are trying to ignore.

falcor84

Still, it's much easier if 95% of the codebase uses just the core, and the parts that don't are relegated to known here-be-dragons areas, that are always reviewed by a couple of more experienced engineers.

procaryote

also, at least for C++, different people have incompatible ideas of what that core is

t8sr

I've taught programming to some people who had no previous experience with it, and I can tell you that the list of concepts you have to learn at once is basically as long for Python, the quintessential "beginner" language.

The author's argument feels intellectually dishonest for that reason. Especially glaring is the comparison to JavaScript. The latter has an insane amount of concepts to deal with to do anything, including some truly bizarre ones, like prototypes.

Rust is hard to learn, IMO, for precisely two reasons:

1) The borrow checker is in an uncomfortable place, where it's dumb enough that it rejects perfectly valid code, but smart enough that it's hard to understand how it works.

2) As the author points out, there are a lot of levers available for low-level control, precise allocation, etc.

With respect to the second point, the author describes a language he'd like to see: green threads, compiler deciding on allocation, fewer choices and thread safety by default.

This language already exists (minus algebraic types). It's called Go. It's perfectly fine, well-designed and good for beginners. Some people don't like its aesthetics, but that's not reason enough to invent it again, only with Rust-inspired syntax.

diarrhea

Go is not thread safe. It even allows data races in its own runtime. Go 1.25 fixed a nil-checking error that has been sitting in the runtime for two years.

Generally, Go will let you compile just about anything when it comes to channels, mutexes (or not..), WaitGroups, atomics, and so on. It usually compiles as there are no static checks, and then just fails at runtime.

t8sr

That’s a good point. I remember that in the earlier days of Go, there was a lot more optimism about the compiler’s future ability to statically decide more about the program than it currently does. It’s unfortunate that the language never got there.

Sadly, given Google’s new culture and all the people who have left, it seems unlikely it’ll ever get there.

J_Shelby_J

> the list of concepts you have to learn at once is basically as long for Python, the quintessential "beginner" language

IMO, Python is great. But deploying Python is more work than learning Rust, oh and the tooling is something that requires continual education: I hear UV is what all the serious python teams are using now. Better learn it or be left behind!

Meanwhile, vanilla Rust has everything you need. I'm glad I understood sunk cost fallacy and got out of Python after many months of coming up to speed with it.

baq

that's very unfair towards the both uv (uv is great) and the absolutely atrocious state of Python tooling until basically 2025 (slow and brittle, if it was even installed - hello, debian derivatives). uv is the cargo of Python we've been waiting for and it is expected you won't need to learn anything else for a long time.

TylerE

The venue bigger issue with rust as that the compiler is so bitchy it is actively hostile to incremental add-a-line-at-a-time incremental development.

Especially unused variables being a hard compilation error, not a warning.

Ar-Curunir

What? Unused variables are warnings in Rust. Are you thinking of Go?

aeldidi

I find it kind of hard to take this seriously since the JS snippet has a glaringly obvious syntax error and two glaringly obvious bugs which demonstrate that the author didn’t really think too hard about the point they’re trying to make.

I understand the point they’re trying to make, that being that rust forces you to explicitly deal with the complexity of the problem rather than implicitly. It’s just that they conveniently ignore that the JavaScript version requires the programmer to understand things like how async await works, iterators (which they use incorrectly), string interpolation, etc. Just using typescript type annotations alone already gives the js version nearly all the explicitness of rust.

jynelson

> I understand the point they’re trying to make, that being that rust forces you to explicitly deal with the complexity of the problem rather than implicitly

This is not the point I am trying to make.