Zig is more like a smaller C++ than a smaller Rust.
You also don’t have to start with a program that invokes 20 concepts at once, every one of those rust concepts can have its own hello world, introducing one concept at a time. Frankly several of them are just fundamental CS concepts.
And iterators.
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
Well that seems highly unlikely given the huge number of similarities.
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)
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.
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.
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.
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.
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.
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.
I've experienced this myself when starting out and just wanting to make $THING in Rust. A lot of looking things up... then trying it out... then seeing the compiler errors.. then looking up WTF they mean when you don't have solid grasp on X, Y and Z in Rust. Then going down the rabbit hole of mut and clone in order to do what you want... often just cloning because it's easier, even if less performant, only later to understand (a)rc etc.
In another language, you may well get something to run, even if not correct, which can be far more satisfying to correct an incorrect behavior/bug then to have the compiler yelling at you from the start (slowly)... it's a slower and more painful feedback loop to work with. It isn't bad so much as different. That doesn't mean it isn't real, or that I or TFA are bashing Rust.
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.
Any file starting #!/some/path just means for the shell to invoke that command and pass the contents of the file on stdin.
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.
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.
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).
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.
Especially unused variables being a hard compilation error, not a warning.
https://play.rust-lang.org/?version=stable&mode=debug&editio...
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.
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.
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.
khuey•1h ago
https://nodejs.org/api/fs.html#filename-argument
sestep•1h ago
masklinn•1h ago
Which is mostly a lie, since at least half the concepts they gripe about in rust are in the js snippet.
sestep•40m ago
serial_dev•2m ago
jynelson•46s ago
Waterluvian•1h ago
quotemstr•1h ago
Waterluvian•1h ago
ori_b•1h ago
TylerE•48m ago
ameliaquining•41m ago
koakuma-chan•21m ago
Aurornis•5m ago
You can allocate memory for a Vec with Vec::new. Dropping it deallocates. When and where it's dropped is important. Passing ownership around is important. These are parts of managing the memory.
If you need something to be on the heap, you use Box. If you need something to be shared, you use something like Arc or Rc.
Rust makes it nice to implicitly handle the common cases so you don't feel like you're doing manual memory management, but you're making decisions about that memory management at every step of the way.
marcianx•1h ago
`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()`.