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.
> The author conveniently left out all of the things needed to understand that JavaScript version, including async/await, promises, modules, string interpolation, [...] not to mention the runtime that is running this, etc.
These are also left out of the Rust version.
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.
* Same everything-is-an-expression style. Blocks evaluate to the last expression in them.
* /// Doc comments
* ML style pattern matching
* Result type
* 'todo', 'panic'
"Whhaaa but you can find those features in other languages! You literally said ML-style you big idiot!!"
Indeed but Rust massively popularised a lot of those features (how many people actually use ML?) and the number of them makes it almost impossible that it isn't at least strongly inspired by Rust.
Interestingly they have fixed the tuple syntax issue - it's #(a, b, c) - but have copied the match pattern matching mistake where you can write what looks like a variable name and it becomes a pattern. That mistake has been known since the 70s.
>Black lives matter. Trans rights are human rights. No nazi bullsh*t.
No thanks. This is DOA.
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.
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.
The 'difficulty' of Rust would have been preferable, in hindsight.
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.
I’ve spent most of my professional time in C, Ruby, and a decent amount of 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.
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.
And theoretically, I'm not sure it's that very fun to run your game, have it crash because you passed a string to a function that expected an integer, stare at a backtrace, see where that variable came from, go up the call stack a few levels, and then realize "oh, i forgot to parse that string after the user typed it in". I'd rather get a compile error that underlines the problematic code and says "this is a string, but the function expected an integer". It may be debugging compiler errors all day, but the alternative is debugging runtime errors all week.
I think worst case it's a "sink or swim" course where a large fraction of the cohort wash out and that's bad for numbers (which will annoy bean counter but for a prestige university might actually be OK medium term) and best case the wash out rates are no different but the good students are receiving a lot more value than for today's First Language which is (at the university I'm thinking of) Python.
I think the move assignment semantic and the use of "const" to mean constant are examples of things where Rust is significantly penalized by having older languages teach their insane choices as just "How it is" so that then later a Rust course needs to have students un-learn this stuff when it would be easier to begin there.
Compiler errors are by nature often counterfactual: "compiler couldn't prove that this wasn't none" or "once you pass through this generic method it's no longer known that your list of Animal only contains members of Dog" is usually more confusing and less tractable than a concrete test case that craps out your program. Then you can start poking away with prints at the stacktrace.
If you step through every single line of your execution carefully and inspect all the data, you're virtually certain to unstick yourself. I can't say the same if you get some gobbledygook from the compiler.
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.
Read up on the details of each one when proposing the design for Cargo script to see what we could learn.
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.
I think those features have since spread to C# interactive (probably inspired by the F# incubator IMO), as that language has done things to simplify its syntax to make single file apps easier. From your comment Rust seems to be taking a similar approach.
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).
I sympathise, but in 2025 that is a terrible reason to choose a system.
A lot has changed, mostly for the better, much better, in the last twenty years
Those aren't good reasons to choose something?
I mean, sure, I COULD use Python or Go, or actually build small programs in a number of other languages instead of scripts altogether... But Deno+TS is actually a pretty good and capable shell scripting option. I'm not bashing on Python or Go here.. but given that I KNOW one of these options better than the others, it definitely is more than enough to tip the scales.
Unless you're making the assumption that my starting with JS so long ago means I don't understand modern/current conventions?
In fact, in 2025 I tested same setup for better scripts: deno+ts.
I know .ts pretty ok, but the pattern didn't stick to me with deno, especially when Python received uv.
But both options are fine. Saying that in 2025 you should so something different and more modern and not elaborating makes 0 of an argument.
PS C#/.NET just introduced "run", won't be much sense to use deno+ts once it gets up to speed as native integration.
I want the dotnet run to work out, that means I could start using C# more. We have a mixed bag now Go(biggest chunk), C#, Python, JS/TS, and lots of .sh. Some powershell(in search for better shell scripting). Some very little Rust.
Do you do any GUI apps with C#? If yes what you go for? Did MAUI took off already, or it's not being well adopted? The promise was nice. I still miss Delphi and drag and drog components. Well there is Qt now, but that's a different story.
I don't do a lot of desktop gui apps, I've thought about Tauri wrapped web-based apps, mostly in that the tooling seems pretty nice, there's also Leptos and a few other options that can work with/similarly. If going with C# I'm more inclined to use Uno, Avalonia, Etp Fprms or maybe embedding Blazor. MAUI is kind of DoA for me, only because of a lack of Linux target. I know it's only 5-6% of desktop market, but IMO, it's still worth having given a developer audience.
I know web-based desktop apps are a bit higher overhead than native, but they can operate relatively well with good skinning (CSS) and accessibility features that tend to work better, or at least more consistently than a lot of cross-platform UI tooling. I find MUI + React to be a pretty good mix for UI, and have played with async state mgt similar to Redux in managed (backend) code with it a bit, and it's worked pretty smoothly in my experiments. You have to think a bit more about state vs. events, but it's been a rock solid experience.
Bash, if you must
Docs are at https://doc.rust-lang.org/nightly/cargo/reference/unstable.h...
Yes, there has been a long road to this in defining what this should look like, how it should interact with the language, what is the right scope for the initial release, and so on.
At this point, I'm doing what I hope is the wrap up work, including updating the style guide and the Rust reference. The big remaining work is in details I'm working out still for rustfmt and rust-analyzer. Other than those, I need to get to a bug fix in rustc and improve error reporting in Cargo.
For myself, I use cargo script nearly daily as I write a script whenever I'm creating a reproduction case for an Issue I'm interacting with.
Can you explain more? Is it this - https://stackoverflow.com/questions/7707178/whats-the-approp... ?
#!/usr/bin/env -S go run
I'm not sure if/when go ignores a shebang on the first line... otherwise, there are a bunch of articles I've seen that have a slightly differing format to do the same.. but google results feel off/old.searched for: go shebang scripts
shebang is the term for a text/script file beginning with "#!" with the executable and parameters to run.
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 easy thread safety.
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.
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.
Sadly, given Google’s new culture and all the people who have left, it seems unlikely it’ll ever get there.
Your claim here is that the author's argument is intentionally misleading. That's an awfully strong accusation, and you don't support it in your comment.
You're also immediately undermining your own argument when you go on to list difficulties in rust that javascript doesn't have.
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.
Dyn-safety is another but I had encountered that previously in Swift.
I love that.
My happiest professional programming has been C
I guess diversity of taste is a wonderful thing?
I believe everything in this post (except `cargo -Zscript`) was in the Rust of 2018.
* I think Rust gives the compiler too much freedom to choose whether or not to apply Deref (and in what order). The whole .into() and From trait allows the compiler to perform arbitrary type conversions to make the code work (the standard library is full of similar "convenience" traits and functions). All of these tend to hide the types of a objects, making it hard to map a function call to an implementation (though a good IDE can help with that). * I think implicit return values is a misfeature as it makes flow control implicit, hiding it from programmers reviewing the code. I'm also not fond of the question mark operator, though syntax highlighting helps a lot with that. * Rust modules are generally too small so that you need hundreds of dependencies to do anything useful. Each of which you need to separately vendor and periodically update if you need deterministic builds. * Async Rust is a hot mess right now
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.
This is not the point I am trying to make.
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
the article itself says, clearly, that the (short) rust program requires knowledge of a significant number of non-trivial language features, as well as the behavioral outcomes of all of their combinatorial interactions -- approximately none of which are relevant to the problem that is being solved by that program!
what I expect is that a language adds as little cognitive complexity (overhead) as absolutely possible, when it is used to express a solution to a given problem
Why do you think that a simple implementation follows from a simple explanation? As an example, see XKCD 1425[0], whose transcript I include here:
> Cueball: When a user takes a photo, the app should check whether they're in a national park...
> Ponytail: Sure, easy GIS lookup. Gimme a few hours.
> Cueball: ...and check whether the photo is of a bird.
> Ponytail: I'll need a research team and five years.
> In CS, it can be hard to explain the difference between the easy and the virtually impossible.
As the other comments have said, in other languages you face the same problems, those languages just won't help you handle them. Not all filenames are printable, but most languages don't help you deal with this. Almost all languages have some way that functions can fail and not return the kind of value you wanted - in Rust this is done by having a return type that shows it might return a different kind of value, in other languages this is done by having a novel concept of "exceptions" and you have to worry about whether every function is "exception safe", which is not actually simpler even if it looks like it at first glance. Etc.
literally every filename is printable, the question is only how to render the filename in a "printable" form, which is a function of the filename and the destination output
this isn't an interesting problem, every language and/or its stdlib should have reasonable defaults for this kind of thing. these kinds of details are exactly the kinds of things that a program like the one in the OP shouldn't need to care about, unless they explicitly opt-in to that complexity
> in other languages you face the same problems, those languages just won't help you handle them.
good languages let you handle these sorts of problems, but they don't force you to handle them. whereas rust lifts all of these problems up to the programmer directly and unavoidably and says "hey you need to deal with this"
managing low-level details like ownership or memory management or whatever isn't somehow inherently virtuous or valuable
Nope. Filenames on Unix can be arbitrary byte sequences, and even on Windows they can be characters that don't exist in the current locale.
> this isn't an interesting problem, every language and/or its stdlib should have reasonable defaults for this kind of thing.
It's not an interesting problem until you hit it. OSes should set better standards, but given that they can't or won't, every application needs to handle that case.
In which case(s) it is the responsibility of the thing that wants to print them to make them printable, right?
I guess we're using different definitions of "printable" which makes this a discussion rooted in semantics which isn't very interesting.
Which makes surfacing that responsibility to your application code, as Rust does, better than e.g. silently turning them into empty strings, as some other languages do, no?
i mean you can create a file with name `0x01 0x04 0xff 0x0a` but it's not like e.g. `ls` handles this stupidity
The last section gives two different hints as to what this "smaller and cleaner" language might be, but neither of them fully makes sense to me.
First, withoutboats's "Notes on a smaller Rust". That post and especially its sequel are great and I like them a lot, but the title is fairly misleading as to what they're getting at. The language that boats sketches out in those posts has significantly different design goals from Rust; in particular, it abandons the requirement of low-level programmer control over runtime behavior, and so is unsuitable for many use cases that Rust is used for. The idea, rather, is to explore what lessons Rust can offer for the design of a language with more "mainstream" requirements (i.e., one that can afford things like a tracing garbage collector, and wants to avoid Rust's downsides compared to other popular languages, like slow compile times and heavy syntactic salt). That language is not "struggling to get out" of Rust; Rust doesn't want to be it.
Second, "In a manner of speaking, that smaller Rust is the language I fell in love with when I first learned it in 2018. Rust is a lot bigger today, in many ways, and the smaller Rust is just a nostalgic rose-tinted memory." I've explained above why I don't think boats's proposed "smaller Rust" is anything like the real Rust was at any point in its history (at least after the very early days, once the designers figured out that they were targeting C++'s niche). In most fundamental respects, Rust hasn't changed that much since 2018, and a lot of the changes (like the new editions) are about making it more syntactically flexible and increasing the fraction of sensical programs that compile. That said, there are two big exceptions: async and const, which were much more minimal in 2018 and have since expanded to big complex meta-features with many interlocking parts that weren't part of the language's original core. If the claim is specifically that Rust was smaller and cleaner before async and const, then by all means, say that! But the post doesn't, leaving us to try to figure out what was meant.
Austral? https://austral-lang.org/features
I take what might be a slightly different read of matklad's point; I don't think Rust has much compromised its vision in terms of which broad features to support, but it has on a couple occasions chosen to ship something that wasn't perfect because being useful requires taking only a bounded amount of time to iterate on design.
So Rust 1.0 shipped without async, even though it was known to be needed for some of Rust's core use cases, because it was too far from being ready and it wouldn't do to wait forever. Once that decision was made, it had implications for how async could work; in particular, really doing it right requires linear types, but this wasn't appreciated when Rust 1.0 shipped and it's not a backwards-compatible change, so by 2018 it was off the table. The choice was, do async in a way that works with the existing design decisions, at the cost of some elegance, or don't do it at all. The former choice is not just more "industrial", I would argue that it coheres better, because waiting for multiple events at the same time is a core feature that a language for foundational software has to have, and the combinator-based approach that people were using in 2018 cohered poorly with the rest of the language (e.g., requiring unnecessary heap allocations). So this wasn't really a compromise to coherence.
(This also happened on a lesser scale when async/await first shipped—e.g., specific "async" syntax instead of a more general coroutine feature—because of eagerness to ship something that year. boats has claimed that this was a matter of existential survival for the language; I'm not sure I agree. But while async/await is a bit less conceptually pure than fully general coroutines, I don't believe that any of today's common complaints about async are downstream of the decision at that time to try to ship something quickly; there don't seem to have been a lot of obvious mistakes from then.)
(My understanding is that const has a similar story but I'm less familiar with the design space there, because people haven't exhaustively chronicled its history like they've done with async, perhaps because it's not as heatedly controversial.)
It was pretty much off-the-table well before that, because a usable implementation of linear types requires being able to ensure the absence of panics. (A panic must unwind the stack, which amounts to automatically running drop implementations.) The two issues are quite closely linked, and hard to address in isolation.
For instance if you’re dealing with database transactions you probably want to make it explicit whether you commit or rollback, but on panic you can likely allow the transaction to be cleaned up automatically.
I’m not just saying that I want to go back to the “good old days”, I really do think that those parts of Rust were designed as a coherent whole, in the same way that Uiua is designed as a coherent whole.
I think there's an argument to be made that you could in fact make a simpler language than Rust while keeping the core concept. This variant of the language would remove:
- the Copy trait
- reborrowing
- deref coercion
- automagic insertion of `into_iter` in loops
- automatic call to drop at the end of scope (instead you'd have to call it by yourself or get an compiler error)
- trait bounds having an automatic `:Sized` bound by default.
- lifetime elision
- no “match ergonomics”
- and likely a few other pieces of “magic” that can be hard for beginner to grasp, but that's what I had at the top of my head.
This language would be much simpler, by having fewer concepts and a lot less “magic”, but it would also be much more cumbersome to use in a day to day basis, as all of the above are clever workaround designed to make common tasks as straightforward as possible, and I don't think anyone would prefer to use it than using Rust itself. It may be useful as an instructional tool when introducing Rust to students though.
Pretty much all of the features in the list are things that either I have struggled with when learning Rust (the Copy trait and lifetime elision), or I've seen beginner struggle understanding (both new hires, or students at the place when I gave Rust lectures).
The rest, sure, you could do without (reborrowing can't be emulated but I don't think it's strictly necessary to write real code). I'd add catchable exceptions and the use of traits instead of explicit modules as things that I think tremendously complicate the language semantics and are almost certainly not strictly necessary to achieve Rust's language goals.
In any case, I think it's just true that `Copy` is quite fundamental to Rust. IMO even if you could somehow turn all instances of it into syntactic sugar (which I think is not true, as the `Cell` example shows), the surface language you used would be sufficiently unlike Rust that it wouldn't really be Rust anymore.
1. “Within C++, there is a much smaller and cleaner language struggling to get out”
2. However just subsetting the language to get at the smaller one would not be a cleaner language. Instead we must first make a superset language, adding features, then we can subset this new language to reach our smaller but cleaner C++
3. Step one, superset will land in C++ N+1. Planning of that "subset of a superset" will need to wait until we've completed that work.
4. C++ N+1 is an even clunkier behemoth. Rinse and repeat.
I don't understand why people who've seen this happen more than once would stick around. You're not going to get the "smaller and cleaner" language after step two, there is no step two, it's just going to be step one again and then step one again, and then step one again, forever.
I'm quite familiar with C++ as well and this just jives so much, each standard is just almost exponentially more complicated than the last, and while there are good changes they don't necessarily fit well with the prior version and its just a mess, I still maintain two OSS libs but I don't use the language anymore.. so its a question of how long I put up with it at this point.
Rust is such a breathe of fresh air coming from c++11/14/17/20 but its still a behemoth if you don't know the entire thing, I think this article is pretty spot on with that.
Generally all of the interfaces conform to the patterns in the mem module. If you want to understand the structure of everything else unambiguously it would be best to start there: https://doc.rust-lang.org/std/mem/
khuey•5mo ago
https://nodejs.org/api/fs.html#filename-argument
sestep•5mo ago
masklinn•5mo ago
Which is mostly a lie, since at least half the concepts they gripe about in rust are in the js snippet.
sestep•5mo ago
serial_dev•5mo ago
jynelson•5mo ago
Waterluvian•5mo ago
quotemstr•5mo ago
Waterluvian•5mo ago
ori_b•5mo ago
TylerE•5mo ago
ameliaquining•5mo ago
kiitos•5mo ago
but file watcher programs, or http services, or really anything that runs on modern linux servers, are not these use cases!
koakuma-chan•5mo ago
Aurornis•5mo 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.
marcus_cemes•5mo ago
> This function is not magic; it is literally defined as: pub fn drop<T>(_x: T) {}
This is usually more deterministic than GC languages (no random pauses), but can be less efficient for highly nested data structures. It also makes linked lists impossible without using "unsafe rust", as it doesn't abide by the normal ownership rules.
[1]: https://doc.rust-lang.org/rust-by-example/scope/raii.html [2]: https://doc.rust-lang.org/std/mem/fn.drop.html
sshine•5mo ago
Admittedly not the easiest language to make a linked list in.
mtlmtlmtlmtl•5mo ago
It's easy to fall into a trap where your Banana class becomes a GorillaHoldingTheBananaAndTheEntireJungle class(to borrow a phrase from Joe Armstrong), and nothing ever gets freed because everything is always referenced by something else.
Not to mention the dark arts of avoiding long GC pauses etc.
It's possible to do this in rust too, I suppose. The clearest difference is that in rust these things are explicit rather than implicit. To do this in rust you'd have to use 'static, etc. The other distinction is compile-time versus runtime, of course.
mattashii•5mo ago
You could use 'static, or you can move (partial) ownership of an object into itself with Rc/Arc and locking, causing the underlying counter to never return to 0. It's still very possible to accidentally hold on to a forest.
Bratmon•5mo ago
Can you elaborate on this? I'm struggling to picture a situation in which I have a gorilla I'm currently using, but keeping the banana it's holding and the jungle it's in alive is a bad thing.
lmm•5mo ago
BananaaRepublik•5mo ago
Measter•5mo ago
saghm•5mo ago
steveklabnik•5mo ago
fiedzia•5mo ago
pjmlp•5mo ago
Cedar being one of the very first ones.
Whose ideas perculated to Modula-2+, Modula-3, Oberon, Oberon-2, Component Pascal, Active Oberon, D, C# (after Midori learnings finally found their way into the language), Swift, Chapel, and whatever comes next where researchers now try to mix both productivity with modern type systems.
marcianx•5mo 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()`.
ptdorf•5mo ago
> console.log(`${kind} ${filename}`)
It should be `eventType` (string).
khuey•5mo ago