well that's not always the case - I live in place where you can jog with earphones at 2AM and only worry about drunk drivers (very rare)
as a local, there was a lot of places that are "visible to foreigners but invisible to locals" -- cafes/view spots/hipster-places that only advertises to foreigners (they didn't even have signboards)
I learnt about those places when some foreign friends took me there
> I am so tired of worrying about & spending lots of time fixing memory leaks and crashes and stability issues. it would be so nice if the language provided more powerful tools for preventing these things.
Zig is a middle ground. It solves some of the common foot-guns in C, Without the costs of affine substructural typing that offers Rust its super powers.
I am of the opinion that it is horses for courses and not a universal better proposition.
Because my needs don’t fit in with Rust’s decisions very well I will use zig for personal projects when needed. I just need linked lists, graphs etc…
While hopefully someone can provide a more comprehensive explanation here are the two huge wins for my use case.
1) In Zig, accessing an array or slice out of bounds is considered detectable illegal behavior.
2) defer[0] allows you to collocate the the freeing of resources with code.
That at least ‘feels’ safer to me than a bunch of ‘unsafe’ rust that is required for my very specific use case.
I was working on some eBPF code in C and did really miss zig.
For me it fits the Pareto principle but zig is also just a sometimes food for me, so take that for what it is worth.
Fwiw you don't need unsafe for graphs or linked lists in Rust. At least not directly - these things can be abstracted. The petgraph crate is the most popular for graphs. I'm not sure about linked lists because linked lists are the wrong choice 99.9% of the time.
I've written hundreds of thousands of lines of Rust and outside of FFI, I've written I think one line of unsafe Rust.
Not really though. That's like saying that no language is "safe" because the compiler could have a bug.
It's true that safe wrappers around unsafe code sometimes have bugs in them, but it's orders of magnitude easier to get the abstraction right once than to use unsafe correctly in many places sprawled across a large codebase.
I think he meant "show me a true linked list / node graph in rust that isn't unsafe". The reason being its not possible using c-style pointer following (or without just putting everything auto-pointers). What you've shown is exactly the tradeoff they were referring to. In rust, the answer is: make sure lifetime of all memory is explicitly managed, then use integers for the 'links' between nodes.
His point was that for his programming, he wants to be able to make real pointers and real linked lists with memory unsafe, which Rust makes difficult or opaque. For example with linked list, you could simulate (to avoid unsafe), by either boxing everything (so all refs are actually smart pointers), or you can use a container with scoped memory lifetime, and have integers in an array that are the "next" pointer. In addition to extra complexity, the "integers as edges" doesn't actually solve the complexity, it just means you can't get a bad memory error (you can still have 'pointers' that point to the wrong index if you're rolling your own).
Same with your graph code. Using a COO representation for a graph does in theory make it "memory safe" (albeit more clumsy to use if you are doing pointer-following logic), and it also introduces other subtle bugs if your logic is wrong (e.g. you have edge 100 but actually those nodes were removed, so now you're pointing at the wrong node).
I think the point (which I agree with for things like linked list, graph, compiler) is that depending on your usecase, the "safety" guarantees of rust are just making it harder to write the simplest most understandable code. Now instead of: `Node* next` I have lifetimes, integer references, two collections (nodes and edges) to keep in sync, smart pointers, etc. Previously my complexity was to make sure `next != null`, now its a ton of boilerplate and abstractions, performance hits, or more subtle bugs (like 'next' indices getting out of sync with the array of 'nodes').
If there was a way to explicitly track the lifetime of an arbitrary graph/tree of pointers at compile time, we wouldn't need garbage collection -- its not solvable at compile time, and the complexity has to live somewhere.
> it also introduces other subtle bugs if your logic is wrong (e.g. you have edge 100 but actually those nodes were removed, so now you're pointing at the wrong node
This is not actually a different kind of bug; it's just use-after-free, which you can of course get when using pointers instead of indices.
Actually it's slightly safer than pointer use-after-free because it is type safe and there's no UB.
Also some of the Rust arenas give you keys (equivalent to pointers) which can check for this. There's a good list here (see "ABA mitigation"):
Forgive me if I've mis-understood this thread, but there are unsafe declerations in that crate. Is there really any difference between using unsafe in your own code, versus wrapping it inside some crate?
I guess you are making the point that the user does not have to concern themselves with the unsafe declarations?
I would say yes, there’s a difference, in general. I would much rather leave the unsafe code to crates used and tested by many other applications, than have them in the application code itself.
> Is there really any difference between using unsafe in your own code, versus wrapping it inside some crate?
Yes, in the same way that there's a difference between using `std::Vec` (which uses `unsafe`), and writing an unsafe Vec class yourself.
Or even the difference between using Python (which wraps an unsafe CPython implementation), and doing everything in unsafe Python code.
The difference is that widely used code like CPython and `std::Vec` are much much better tested and audited than anything I would write myself, because so many people use them. This is a continuum so something like petgraph is going to be not as well tested as std::Vec but still way better tested than anything I've written.
I don't think it's unreasonable, even though I am getting marked down for daring to ask, for people who are making assertions, even if they are well understood *within their own community* (that is, not necessarily universally known) to show examples of what they are talking about.
You're correcting someone, so it's clear that your understanding isn't universal, and example code is the absolute minimum.
zig is unmanaged memory. But rust also allows memory leaks, and they're not uncommon in large, complex programs. So this rewrite will not necessarily control for that.
There are two kinds of memory leaks: forgotten manual freeing (all references are gone, but allocation is not) and forgetting to get rid of references that keeps an allocation alive. Both are a kind of logical error, but the first is mostly possible in languages with manual memory management. The second one is a universal logical error (only programmer knows which live references are really needed).
In the Haskell community I’ve seen the second kind called “space leaks.” I don’t see it used much outside that community but I like the term and use it when talking about other languages as well.
I suppose all languages allow them, depending on how you define a memory leak. Garbage collected languages generally prevent them, since you never have to explicitly free memory, but if there are reference cycles, that memory can never be freed automatically. Rust has the same problem, but since rust uses lifetimes to understand when to drop things, many people expect that this will mean there can be no memory leaks, but leaks are not considered a correctness or safety issue (oom is a panic and panic is safe!). Not only explicitly possible (through Box::leak) but also possible by mistake (again, usually through reference cycles).
which is a good thing. C++'s RAII is magic-sauce that does a lot for you when you can simply use `defer` in zig. A constructor is just a function call. A destructor is just a function call.
Does defer in zig track the objects lifetime directly, or is it like the various other 'context' features in other languages where it only really works for lifetimes of function-local variables and leaves you on your own when things get more complicated? (which, IMO, is precisely when RAII becomes most useful. It does seem like most of these languages only consider the 'forgetting to cleanup on an early return from a function' case)
It's not a good thing. The reasoning is extremely simple and I don't understand how can anyone oppose it: there are some operations that you don't want to forget BY DEFAULT.
If I open a file, eventually I want to close it. If I allocate some memory, eventually I want to deallocate it.
Any programming language design that intentionally puts the onus BY DEFAULT on the user to *not forget to manually do something* is honestly asinine.
Defer has a place (I do use defer in C++, in fact you can implement it with RAII, proving that RAII is strictly more powerful/more flexible), but the default should be the safest and most straightforward option.
Also "magic-sauce that does a lot for you" is just false. It's literally a function call injected at the end of a scope.
Whether you consider it magic is up to you, but, unlike a destructor in RAII, there is nothing automatic going on. If you don't explicitly invoke a destructor, you won't get a destructor.
The fact that you can explicitly invoke the destructor to happen later is simply syntactic sugar, just like if/else/while, or any other control construct more powerful than a conditional jump instruction.
And more importantly, you can choose what destructor to call. This is perhaps what's most underrated about defer, because defer can select among many different destructors possible, at multiple different levels (group free with arenas, individual free, etc).
Or even whether you need a destructor, or something simpler, like nulling out a pointer or two to break a reference loop.
defer is a perfectly general structured flow concept; it only cares about when you do something, and is completely orthogonal to what you need to accomplish.
> When you explicitly invoke a "destructor", you do it on many code paths (and miss one or two)
Unless, of course, you do it inside a defer block.
> You don't specify where the `defer`-red "destructor" will be invoked.
Yes, actually, you do. It is patently obvious, by code inspection, where the destructor, or anything else specified in a deferred block, will be invoked. defer is a perfectly cromulent part of structured control flow, allowing for easy reasoning about when things occur without having to calculate an insane number of permutations of conditional branch instructions.
It'd take more than that to match rust's borrow checker. Rust's borrow checker tracks lifetimes, and sometimes needs annotations in code to help it understand what you're actually trying to do. I suppose you could work around that by adding lifetime annotations in zig comments. Then you've have a language that's a lot like rust, but without an ecosystem of borrowck-safe libraries. And with worse ergonomics (rust knows when it can Drop). And rust can put noalias everywhere in emitted code. And you'd probably have worse error messages than the rust compiler emits.
Its an interesting idea. But if you want static memory safety in a low level systems language, its probably much easier to just use rust.
> I suppose you could work around that by adding lifetime annotations in zig comments.
you can make a no-op function that gets compiled out but survives AIR
> rust knows when it can Drop.
and its possible to cause problems if you aren't aware where rust picks to dropp.
> And rust can put noalias everywhere in emitted code.
zig has noalias and it should be posssible to do alias tracking as a refinement.
> But if you want static memory safety in a low level systems language, its probably much easier to just use rust.
don't use that attitude to suck oxygen out of the air. rust comes with its own baggage, so "just using rust because its the only choice" keeps you in a local minimum.
> and its possible to cause problems if you aren't aware where rust picks to drop.
Can you give some examples? I've never ran into problems due to this.
> don't use that attitude to suck oxygen out of the air. rust comes with its own baggage
Yeah, that's a totally fair argument. One nice aspect of the approach you're proposing is it'd give you the opportunity to explore more of the borrow checker design space. I'm convinced there's a giant forest of different ways we could do compile time memory safety. Rust has gone down one particular road in that forest. But there's probably loads of other options that nobody has tried yet. Some of them will probably be better than rust - but nobody has thought them through yet.
I wish you luck in your project! If you land somewhere interesting, I hope you write it up.
> If it's doing a drop in the hot loop that may be an unexpected performance regression that could be carefully lifted.
Yeah, I've heard of people being surprised that when they make massive collections of Box'ed entries, then get surprised that it takes a long time to Drop the whole thing. But this would be the same in C or Zig too. Malloc and free are really complex functions. Reducing heap allocations is an essential tool for optimisation.
The solution to this "unexpected performance regression" in rust is the same as it is in C, C++ and Zig: Stop heap allocating so much. Use primitive types, SSO types (SmartString and friends in rust) or memory arenas. Drop isn't the problem.
yeah, IMO generally explicit is better. It's hard to take something implicit and increase the visibility (I'm aware there are tools to show you lifetimes in rust). But another option is to statically analyze the code (or the IR) and have something else check that you aren't leaking.
It is quite obvious that Zig is pre 1.0 with thousands of stranded unsolved issues (per their GitHub repo). A review of Zig hype gives the strong impression it was created by being relentlessly and suspiciously pushed on HN, beyond logic or its language rankings (per TIOBE or GitHub stats), so that many were under the illusion that the language was something more or other than what it really is.
Zig is still under development and beta. Stability, crashes, and leaks should not be surprising, and even expected. To stick with a beta language, usually companies and developers are philosophically and/or financially aligned with the language. An example is JangaFX and Odin, where they not only have committed to using the language (despite being beta) in their products, but have directly hired GingerBill.
Team Bun appears to have "alignment and relationship issues" with Zig, to the point they have decided to extensively explore their options. Now Bun is rewritten in Rust. They are seeing if Rust solves their requirements. As with any relationship, if one ignores or takes a partner for granted, don't be surprised if they want a divorce or jump to someone else.
Zig very much could of moved all of their GitHub issues over to Codeberg, to be resolved, but chose not to do so. Thus left thousands of issues unsolved and stranded.
This maneuver was arguably obfuscated by the anti-LLM stance and finger pointing at Microsoft, but nevertheless, many still have noticed. Zig, for a long time, had been falling behind and doing poorly on their open to close ratio for resolving issues. It should be embarrassing to leave so many issues open.
Even if not accepting new GitHub issues, they have demonstrated an inability to resolve existing issues, except at an extremely slow pace. Considering there are just about no new issues on their GitHub repo, it is understandable if there are those that find the pace to close and amount of issues unacceptable or questionable, in addition to the clearly bad open to close ratio.
Did you read their migration post? They are thinking about it as COW, so they're using both issue trackers right now, but as soon as the update an issue it jumps straight to the Codeberg issue tracker. It's an unconventional way of doing it, but it's no conspiracy.
Just to make it clear, I genuinely think they offer a crap deal. They justify being expensive, but what the end user gets in return is not worth it IMO. Do not host anything on Vercel if you can avoid it.
The point I'm making is that the billing becomes very clear once you treat them like a PaaS, not a cloud platform. It's like buying individual seats for corporate software that just happens to also host your application as a side effect. I feel like they make this fact pretty clear on the pricing page.
"$20/month" = a single license for vercel's own tooling
"+ additional usage" = whatever AWS + markup costs... they SHOULD link to the /limits docs [0] from here
"$20 of included usage credit" = "free" coupon to use the overpriced AWS services with the pitiful soft-limits listed in detail below
"Drag the sliders. Watch the $20 plan disappear." is a misreading of vercel's pricing chart. "Vercel Pro" was never 20$, especially not for 5 users, since that's 5 licenses for vercel's tooling, which is the ONLY thing they make here. You essentially get a coupon letting you use that tooling on AWS via their control panel, but beyond that they have 0 involvement in the cloud market. They list the soft limits under the column in the price chart, and they have that /limits page detailing their insanely marked up overage charges. [0] IMO, that's not hidden, it's just a bad deal.
They selfishly assume their tooling IS the product you're here for and whatever hurdles exist to use it will just be tanked. "theupsellgame.com" also complains that the hobby plan has no way to pay for it. Why would I sell the supermarket apples at my fruit stand placed directly in-front of the supermarket if you aren't going to also buy my superior Apple Eater's Experience package.
Again, I think they're leeches. I just think this site uses weak arguments for why Vercel is awful.
well people want to finish their work and go home, that's why
I know HNers don't like "surveillance everywhere", but...
if you're some law enforcement, every chance to get info means hours/days saved on your work... so you reach for the "easy-way": if you can get comms of a drug gang, you can identify who belongs to that gang (instead of risking their own life by actually 'joining' the gang)
But... some do cross their lines (eg watching comms of their ex, getting paid by political actors to listen over opponents, etc)
it's not like law enforcements are 100% bad guys, but things are "complicated"
It's mainly a problem of consequences and accountability. The people who suffer unjustly from unlawful surveillance and overreach are usually unable to do anything about it, and they are assumed to be criminals anyways so nobody cares. Punishments for violating the law are nearly nonexistent for "law enforcement", so a culture of impunity is formed that cannot be easily fixed. Anybody trying to enforce the rules would run into both corrupt and noncorrupt noncompliance, just like trying to get fast food workers to follow health and safety guidelines. It's probably impossible to reform and only a wholesale teardown and replacement without keeping anyone contaminated by the existing culture has a chance.
To the extent that locking exists in posix it is various degrees of useless and broken. And as far as I know while BSDs have extensions which make some use cases workable Linux is completely hopeless.
> When you make a ceasefire and then strike first, that’s called being the aggressor.
Oh boy, let me tell you about October 7th. Attacks by Hamas, Hezbollah, Houthis, and Iran followed. Oh, and half a dozen other Palestinian groups were involved in 10/7 but they don't like to talk about that.
> How many civilians has Israel killed since oct 7? When is it enough?
Probably not too far off from how many Iran has killed in the same timeframe (of course, they are killing their own). Iran killed 30,000 of their own just this year.
And just so we're clear, Iran supported Hezbollah in Lebanon and Syria, and the Houthis in Yemen, both or whom are responsible for easily 10x as many deaths as Israel (total). The civil wars in Lebanon and Syria left millions dead, and the one in Yemen also resulted in hundreds of thousands dead.
> Israelis also rape, kill, and do other vile things to prisoners, innocent or guilty, who they imprison with or without charge.
well but do israelis parade their dead rape victims openly?
> When you make a ceasefire and then strike first
well that's between trump and iran? did netanyahu agree?
I agree that netanyahu is being a dick here: he should have focused on iran, instead of invading lebanon. That alone is a huge political/PR mistake
but... how's that ceasefire related? is israel a proxy of usa? does Trump control israel directly?
Ethically, the israel politicians goes at great length NOT to damage civilians: the walkie-talkie bomb is a classic example of "try to kill all the militants WITHOUT carpet bombing"
(though they failed to "kill all" with that scheme, and... well they did bomb a lot after that)
> well but do israelis parade their dead rape victims openly?
1) why is that an important distinction?
2) but since you asked, they do, western media just refuse to show it but all you need to do is follow a bunch of israeli instagram accounts and you'll see more than enough sooner rather than later
> 2) but since you asked, they do, western media just refuse to show it but all you need to do is follow a bunch of israeli instagram accounts and you'll see more than enough sooner rather than later
woah... big claims here! maybe you should post source?
One side openly tries to do maximum death on everyone including infants (eg. fire random missiles, intifada, and the oct 7th attack)
The other side at least tried their best NOT to attack back (expensive missile defense systems) or at least kill only the militants selectively (walkietalkie boomboom)
I mean, you should be ashamed of even comparing israel vs iran/hamas/etc
> Iran shown more restraint then Israel and USA against other countries
> They played tit for tat.
like... firing missiles at UAE...? launching drone to dubai tower?
did India do anything to iran to get its ships fired upon?
blocking hormuz strait... that alone was enough to trigger global coalition -- though due to Trump's trade dick move to allies... no one sent troops...
if it's "tit for tat", then why does iran make so many un-related countries suffer (eg india?)
well simple: iran is the new pirate of 21st century. nothing more or less.
if anyone says "that's because US attacked", then if I got hit by a car, can I have my revenge on nearby pedestrians?
well oil companies funded "lead fuels are safe" research...
...and it really did backfire (in public relations, politics, etc)
now... I don't think they can actually fund 'research-for-their-profit' -- I mean, would you believe "petro is good for earth" research coming from oil companies, even after the 'lead is good or neutral' research?
Not uncritically, but if the research presents a logically consistent hypothesis, and evidence supporting it, then it would be worth following up on with independent groups and if it remains consistent to scrutiny then it should be accepted.
as a local, there was a lot of places that are "visible to foreigners but invisible to locals" -- cafes/view spots/hipster-places that only advertises to foreigners (they didn't even have signboards) I learnt about those places when some foreign friends took me there
reply