In a way I feel like I'm going through what is described in the article but for Zig. I guess Zig is more or less in a similar place now to where Rust was back then. Still I enjoy very much using it already.
but I cant say the same to Zig because I dont see it as (big) update compared to what we have
Still wherever I need absolute code correctness and production grade quality, I use Rust, my favourite language, at the expense of more code and spending more time doing it "the right way".
I was reading an article about rust posted here yesterday and i realized: i have no clue what is going on in this code (also i presume "templage" is a typo):
#[derive(Debug, Default)]
pub struct Context {
authed: bool,
}
#[derive(Template)]
#[templage = "layout.jinja"]
struct HomeTemplate {
ctx: Context
};
pub async fn home() -> impl
IntoResponse {
HtmlTemplate(
HomeTemplate { ctx:
Context::default() }
).into_response()
}
I love Rust and do some advanced code sometimes, but very rarely have I created a macro. I still see it more or less like "magic" that "super-human" library developers master to make their life easier. Typically not my use case.
This is another advantage of Zig. As you may know, metaprogramming in Zig doesn't use any special syntax, but rather the Zig language itself. This is often known as comptime and while not necessarily easy to grasp, as you're reasoning about compile time stuff, at least it's done in pure Zig.
Stuff like
> Also the learning curve for Zig can be steep, especially for those unfamiliar with low-level programming concepts.
I don't think an LLM would start a sentence with "also" like that
> The small and simple syntax is an important part of the maintenance, as it is a goal of the language to allow maintainers to debug the code without having to learn the intricacies of a language they might not be familiar with.
The wording here feels like someone who's a fan of Zig taking a sentence praising Zig's design and trying to rework it into a slightly more neutral encyclopedia style.
IMO, there are things Zig just don’t care about, which in the surface makes it simple but its annoying and burdensome later on.
* Manual interface implementation
* Internals of a struct is public
* No string types
* anytype requires reading code
* Error can’t carry information
* The iteration abstraction in the std is all over the place
* Unused declarations is compilation error
One benefit of this is that if someone tries and bounces, when they try again a year later their experience might be improved enough that they don't bounce again. For a while I was of the thought that the best piece of advice I could give someone wanting to learn Rust was "wait 6 months" :)
I suppose if I find anything I really disagree with I can correct it, so that's a bonus.
2. I've tried to re-use tab bu typing new URL into URL bar and it doesn't work, browser re-open same page and replace URL back!
WTF?!
I would say Rust's borrow checker and lifetimes make it harder to use traditional patterns and favor a more functional approach. Obviously, sometimes doing it the functional way might be hard, for people not so used to it, but it keeps the compiler happier I would say.
When I started out, it felt icky and like some kind of infection that everything eventually had to be async, but that was because I didn't understand how to interact with async code. Using spawn, spawn_blocking, and futures::stream is 90% of my use case, and it makes it easy to set up "barriers" beyond which async doesn't need to spread.
DIP, async/await, coloured-functions, io-monad. All cases where the business logic should go in one column (abstract/sync/blue/pure), and your machinery should go in the other column (concrete/async/red/io). Your logic will remain unit-testable that way, regardless of how big or small it gets.
Irritated newcomers will complain about not being able to call in the other direction. So what's a language-designer to do? Attract the largest possible user-base by not getting in the user's way - or filter out frustrated users and have fewer but better codebases out there?
The typical pattern I enjoy is:
* Sync for the logic
* Async for the job runners b/c I'd like to do other things while it's going.
* Sync or Async as required for the data wrangling (db calls, network, filesystem)
So you have essentially:
1. kick off job, returning a future, by calling an async function.
2. Job is mostly async data wrangling, followed by a sync logic block that's unit tested, followed by an async "save" if required.
3. Either wait for the future, or run the task in the background, or `.await` if you're in an async block.
I'm hand waving away the syntax, but that's the mental model. 99% of code isn't async, and the code that is isn't async for the fun of it.
Especially when using tokio I feel like my solutions work out pretty well. I also very much appreciate how they create async equivalent functions for pretty much any std function worth using. Maybe this creates a divide, but my concurrent programs feel easy to code and the performance is pretty good.
My only semi-issues are probably stuff like task cancellation, however I attribute that to skill issues on my end, rather than tokio or the way async/await is implemented in Rust.
edit: Oh my god, this is your product!? Please, this is a stupid gimmick. Middle click on X11 pastes the selection buffer, a critical feature for my productivity, and now when I try to open links in a new tab I end up pasting text I've selected.
Indeed, there should be a non-editable mode.
"async has a relatively high complexity cost for us due to the 'static bound (cc), cancellation-safety, and restrictions relating to traits and dyn. These currently seem insoluble. Bifurcation between sync and async primitives and ecosystem idiosyncrasies further increase the async tax. Effects-inspired solutions seem unpromising."
"Pre-1.0 Rust had a solution: libgreen. It achieved concurrency in user-space without this bifurcation, but at significant performance, portability and maintenance cost and so was removed. With increased engineering bandwidth this may be worth revisiting. Again the language simplicity would be worth it. (One day I’ll create a PoC of zero-cost wrapping of std::{fs, net} plus fiber::{spawn, select} using generator!)"
I stand to be corrected but I believe that this is design choice of the Tokio async runtime and not a Rust design choice. For example, the Embassy async runtime does not have this bound but then you have to handle pinning yourself. Also, the static bound is supposed to lower the complexity cost, not raise it.
zesterer•1d ago
smokel•1d ago
[1] https://tably.com/
ed_elliott_asc•1d ago
mocatta•1d ago
Noted, and working on it! Pages are copy-on-write as most on the site are intended to be templates where that behaviour makes sense. Working on mitigating annoyances like those observed in these threads. Longstanding browser-specific issues like https://bugzilla.mozilla.org/show_bug.cgi?id=1001790 make this tricky!
lmm•1d ago
SSLy•1d ago
bmacho•1d ago
> Longstanding browser-specific issues .. make this tricky!
I don't think it's true, there are no browser-specific issues that stand in the way of anything that people are complaining about. Or do you have a PoC in whatever browser?
MarkSweep•1d ago
syndeo•1d ago
veltas•1d ago
strken•1d ago