zesterer
> the biggest drawback of async is the fragmentation of the ecosystem
95% of the ecosystem uses tokio nowadays. async-std has been dead for a long while. There are other runtimes for specialist purposes, but pretty much all async libraries will work with tokio, and you should just use tokio. It's fine. It's well maintained. It's not going anywhere. It's hit a stable 1.0. There is basically no reason to not use it.
> So, if you think that you didn't have enough work solving the problems of your users, you now also need to update your toolchains, Dockerfiles, dependencies and more, every 6 weeks.
This is complete rubbish. Rust's edition system means that Rust code written back in 2015 will (largely, bar some minor soundness issues that have been found since then) still compile. You're under no compulsion to update anything, and cargo's lockfiles ensure that your builds don't suddenly break. If you want to upgrade, do so! But it's exceedingly rare that code ever needs to change when doing so. It's about a painless an upgrade experience as it's possible to have in this industry.
> Rust is betting everything on a powerful language backed by advanced theory, but it forgot that developers need more than a language to build solutions to businesses' problems.
No, it didn't. Rust's standard library is not designed to give you everything you need to build a large program. Instead, it's designed to specify the interfaces that other libraries in the ecosystem require to talk to one-another, and it's been remarkably successful at that. Take a scroll through [the docs](https://doc.rust-lang.org/std/) and you'll see that: it's almost all traits, fundamental types, and other shared abstractions that are used by the rest of the ecosystem. Any non-trivial program is supposed to end up with third-party dependencies: the critical thing is that those dependencies can talk to one-another painlessly, and that promise is largely delivered upon: everybody uses the same interface for `Future`, `Iterator`, `From/`Into`, `Allocator`, `Clone`, `Eq`/`Cmp`/`Hash`/`Ord`, `Error`, `Debug`/`Display`/`FromStr`/`ToString`, `Read`/`Write`, `Sync`/`Send`. That's the sign of a remarkably successful and well-engineered set of abstractions.
Source: I'm a core dev for Veloren, which uses a very detailed hydrological simulation for its world generation. More info here: https://veloren.net/blog/devblog-43/
Frankly, I spend a lot of time feeling similarly uncomfortable about my relationship with computers and the industry at large. I think, perhaps surprisingly, I'd call myself a 'technophobe' for this reason.
I think there's a parallel universe out there in which the arc of technology bends toward a future I actually want to live in, but I'm fairly sure we aren't in that universe today. But perhaps if we talk more about how to use the darned things in a manner that enhances the human experience rather than detracts, we can get closer to it.
You can even use tools like trolley to wrap the entire application up in a ghostty-powered shim that presents the application as a native UI application: https://github.com/weedonandscott/trolley
We talk about big-O complexity a lot when talking about things like this, but modern machines are scarily good at copying around enormous linear buffers of data. Shifting even hundreds of megabytes of text might not even be visible in your benchmark profiling, if done right.
When benchmarking, I discovered that the `to_pos`/`to_coord` functions, which translate between buffer byte positions and screen coordinates, were by far the heaviest operation. I could have solved that problem entirely simply by maintaining a list of line offsets and binary-searching through it.
- Software is simpler than you think when you boil it down. There's a massive incentive to over-sell the complexity of the problem a solution is trying to solve, to pull in users. This is true both for proprietary products and, to a lesser degree, FOSS. You can probably replace most of the tools you use day-to-day in a weekend or two - provided you keep practising the art of just building stuff. I'm not saying that you should, but it's worth keeping in the back of your head if a tool is driving you mad.
- You can achieve 80% of the functionality with 20% of the work required to build an off-the-shelf solution. In a surprising number of cases, you can do the same with 20% of the integration cost of an off-the-shelf solution. A lot of software is - to put it quite bluntly - shit (I include a lot of my own libraries in this list!). There are probably only a few hundred really valuable reusable software components out there.
- Aggressively chase simplicity and avoid modularity if you want to actually achieve anything. The absolute best way to never get anything useful out of a project is to start off by splitting it into a dozen components/crates/repositories. You will waste 75% of your time babysitting the interfaces between the components rather than making the thing work.
- Delete code, often. If you look at the repo activity (https://git.jsbarretto.com/zesterer/zte/activity/code-freque...) you'll see that I'm deleting code almost as much as I'm adding it, especially now that I've got the core nailed down. This is not wasted effort: your first whack at solving a problem is usually filled with blunders so favour throwaway code that's small enough to keep in your head when the time comes to bin it and make it better.
- It is absolutely critical that you understand the fundamental mode of operation of the code you've already written if you want to maintain development velocity. As Peter Naur said, programming is theory-building and the most important aspect of a program is the ineffable model of it you hold in your head. Every other effort must be in deference to maintaining the mental model.
We're gonna die, but it's not going to be AI that does it: it'll be the oceans boiling and C3 carbon fixation flatlining that does it.
A fun property of S-curves is that they look exactly like exponential curves until the midpoint. Projecting exponentials is definitionally absurd because exponential growth is impossible in the long term. It is far more important to study the carrying capacity limits that curtail exponential growth.
Oftentimes I find that I enjoy one of the projects so much that I take it further than 'toy', but that usually ups the time estimate by an order of magnitude.
If I want to learn about the structure of ELF binaries, I don't figure it out from first principles. I can't: the decisions that went into its design where highly specific to its history and the sensibilities of its creators, and in a modern context a lot of those decisions are near enough random. These are the sorts of things you should use specs, docs, Google, and maybe an LLM for.
What I'm talking about is, I guess, 'constructive' learning. I might not be able to build my own ELF parser through guesswork, but I probably can write a binary format of my own and a simple OS kernel to read it, given enough time. It probably won't look much like ELF, but the process of discovery that'll happen will teach me about why ELF came to be and what problems is solving, and also about the wider design space that sits around it.
My suggestion is that you should not use an LLM's help for the latter.
I like to think of it this way: if you bolted me to a chair in a room with nothing but a laptop, a text editor, and a compiler, what might I be able to create if you left me for 10 years? What couldn't I create because I wouldn't have sufficient implementation-specific information?
Obviously, you're welcome to do as you please though, mileage may vary, etc.