Live data from Hacker News

Partially Matching Zig Enums

matklad.github.io

141–150 of 170 posts

Re: Partially Matching Zig Enums

#141
post #130

Earlier quoted context omitted.

I don't agree that "you never have to worry about it" unless you're also using smart pointers, which is rarely what I want. I think that the alternative where all allocations and deallocations are made clear (in Zig, allocating routines are "coloured" by convention) is the better alternative, at least for the kind of low-level programming I do and for my way of thinking about low-level code. When I write code where I…

which is rarely what I want. If you don't want memory leaks, it probably is what you want. There isn't a ton of difference between putting a delete in a destructor and using a smart pointer, but the best approach is to go beyond smart pointers and just use a vector, which does everything for you. A lot of this seems like you haven't done a lot of modern C++ to see how elegant and smooth it is.

> If you don't want memory leaks, it probably is what you want.

No, sorry.

> A lot of this seems like you haven't done a lot of modern C++ to see how elegant and smooth it is.

It's true I don't want to use modern C++ (except for certain compile-time tests), and that's because when I write low-level code what I care about the most is being able to see the machine instructions that will be emitted, especially the ones related to memory management (I don't care so much about the computational instructions; the compiler, and the CPU, will rewrite them dramatically anyway).

If I find myself needing pretty abstractions, I reconsider my use of a low-level language. That's also why I'm philosophically opposed to the concept of zero-cost abstractions. What I want from C++ that C doesn't give me is templates and some other compile-time stuff, which are much more convenient for me than C macros. I don't want any implicitness in my low-level code. Zig gives me exactly what I want from a language that specialises in low-level code.

My problem with zero-cost abstractions is that they result in code that looks high-level, while still only really having a low abstraction level (what I mean by a high or low abstraction level is the extent to which I can make local changes without influencing non-local code). The resulting code looks pretty on the page, but makes me work a lot harder to understand what is being executed and when. When I don't want to care about such details, I use Java.

Just last week I had an interesting discussion, that's somewhat similar to this, about Haskell with a colleague. He said something like, look how clearly you can see the algorithm on the screen. And I said, yes, it looks great when trying to understand what it does by reading, but it's terrible to understand when you try analysing it in the debugger or profiler. The point is that there's different kinds of information that code can communicate. Sometimes you want just the function of the algorithm to be clear and want the language to hide execution details, and sometimes you're just as interested in the execution details.

Re: Partially Matching Zig Enums

#142
post #124

Earlier quoted context omitted.

> It really can't be. I just did it.

Fair enough :) I guess one could claim that some feature is useful because it eliminates certain classes of bugs while another is useless because it eliminates certain classes of bugs (which happens to be the more impactful subset of the former class), it's just not a very compelling claim, especially the way you presented it, which is: Something bad happens, say an attacker steals my data. Rust is useful because I c…

Have you noticed how zero is categorically different from the other numbers, even the very small ones? It's an additive identity. No matter how often we sum together zeroes, the answer is still zero and that won't work for other values. Being the additive identity is categorically different, even though it might seem as though zero is just even smaller than a tenth or a millionth, it's different.

In (safe) Rust we categorically don't have type unsafety. Safe Rust function A doesn't have unsafety, and function B which calls it doesn't have unsafety, and function C which calls that doesn't either and so on forever. So in the exercise we talked about the answer is that the fault won't be anywhere in the safe Rust. But because we don't have this in "safe" Zig even though you say there's spatial safety, oops the lack of temporal safety means our apparently OK code might induce the spatial safety issues we thought couldn't exist.

It's OK, the C++ Convener is absolutely convinced of the same line of thinking as you. Surely if they can just keep finding adjustments to make C++ fractionally safer it'll be as safe as Rust. Right? If every three years they make it 10% less unsafe, surely in thirty years it's... oh right, about 65% less unsafe. Huh.

Re: Partially Matching Zig Enums

#143
post #128

Earlier quoted context omitted.

I would say: not the ones with spooky implicit actions and hidden heap allocations, but we won't know until we actually have data. When writing in a low-level language, I always want to know where I'm allocating and where I'm deallocating. Zig makes allocations easier to spot than in C/C++/Rust, and deallocations easier to spot than in C++/Rust. That's just how I like it. I'm not saying everyone must have the same pr…

You might like making and freeing every heap allocation but that doesn't mean it's safer. Every other language would be in the category of 'hidden heap allocations' to a much greater degree. People who understand it don't feel that it is 'spooky'.

I didn't say it was safer, but by "safety" here I don't mean something that will likely work, but an absolute guarantee that it will regardless of what client code does (with the exception of clearly marked unsafe code that's easily found). C++ doesn't offer this kind of safety for pretty much anything.

So we're talking about the likelihood of making a mistake - and of not easily finding it - in the absence of safety. Without any empirical data, all we have to rely on is personal preferences and gut feeling, and those are different from one person to the other. Even expert programmers often violently disagree on what's "better", and I think that's because things can be better or worse for different use cases, but also better or worse for different programmers working on the same problem.

I would like there to be more empirical studies, but I also think we can probably live without them, because software is such an important economic activity that it's under significant selective pressures. If one approach significantly decreases the effort of delivering more value in software, it will spread almost universally (e.g. as unit tests have); the converse is that if something doesn't become universal, then it probably doesn't have a large universal impact.

Re: Partially Matching Zig Enums

#144
post #101

Earlier quoted context omitted.

I've been hearing about how I'll inevitably write all this unsafe Rust for... four years now. Some time back I checked and I had written exactly one unsafe block, and so I inspected it again and I realised two things: 1. It was no longer necessary, Rust could now just do this safely. I rewrote it in safe Rust. 2. It was technically Undefined Behaviour, predictably given the chance to shoot myself in the foot that's e…

You are already narrowing this down to only memory safety, which is part one of the Rust fallacies.

Ah yes, "But what about other safety?". An entire year of hand wringing from C++ people was predicated on this. In one of his rambling proposal papers Bjarne listed all manner of exciting different kinds of safety he'd imagined and which, he assured us, C++ was already almost able to achieve thanks to his wisdom and foresight.

And every single item on his list of course requires the thing C++ doesn't have, memory safety. You can't write software which has any non-trivial properties when it has unconstrained Undefined Behaviour. It really shouldn't be this hard but I have reluctantly accepted that this "argument" is not made in good faith.

Re: Partially Matching Zig Enums

#145
post #140

Earlier quoted context omitted.

> Given enough effort, you can banish all UB and their related CVEs from a codebase. Sure. With infinite energy, anything’s possible - we can prevent all bugs. The problem is, we don’t have infinite energy. > So it becomes a contest of which library had more scrutiny. I.e. you can compare a battle-tested library like cURL to stuff like baby's first XML parser. I agree that software varies in quality, and that differe…

> Sure. With infinite energy, anything’s possible - we can prevent all bugs. The problem is, we don’t have infinite energy. You don't need infinite energy but it is a significant undertaking. The UB seem to obey a power law in regards to their lifetime i.e. every X years number of UB caused problems halves. > I can only recall one serious concurrency bug I’ve ever had (a data race) which took some debugging time to t…

> Even without a chance of UB. You're adding an implicit `Type | null` to every piece that uses nullable code without handling the null case. Each time you forget to do it, you cause either an UB or a null pointer error. And the place it manifests is different from where it's generated. > Furthermore, listening to Tony Hoare's talk (https://youtu.be/ybrQvs4x0Ps?t=1682), he mentions that trying to avoid the null, in the context of a language like Java or C#, that permits them is also causing people to waste time working around them.

It's an insignificant amount of time in my experience, which makes this irrelevant in practice. I’ve never had to "work around them", this is either a theoretical argument or just sloppy programming.

> Sure, but that's not a $0 mistake. It's {time to fix * hourly rate}. Even if you're doing for OSS, you could have been spending that time doing something else.

Oh, come on, you’re smart enough to understand that a few minutes every few months may not be exactly $0, but it’s such an insignificant value that it can be treated as $0.

> Sure. But trading "ease of use" for "preventing errors" is not something I want in any language I use.

Well, you can choose your trade offs, and you can let others choose theirs. So I guess you use Ada for everything? or maybe you use Coq to prove everything? Of course you don’t, you’re also making trade offs, just different ones.

> Null/nil are about as good concepts today as silently skipping errors.

You exaggerate again. I do not agree with that framing, and I back my opinion with experience from practice.

Re: Partially Matching Zig Enums

#146
post #141

Earlier quoted context omitted.

which is rarely what I want. If you don't want memory leaks, it probably is what you want. There isn't a ton of difference between putting a delete in a destructor and using a smart pointer, but the best approach is to go beyond smart pointers and just use a vector, which does everything for you. A lot of this seems like you haven't done a lot of modern C++ to see how elegant and smooth it is.

> If you don't want memory leaks, it probably is what you want. No, sorry. > A lot of this seems like you haven't done a lot of modern C++ to see how elegant and smooth it is. It's true I don't want to use modern C++ (except for certain compile-time tests), and that's because when I write low-level code what I care about the most is being able to see the machine instructions that will be emitted, especially the ones…

Oooh yeah, sorry no, smart pointers and destructors do prevent memory leaks.

You said no then didn't back it up with anything and just went on a tangent of your own personal preferences.

Re: Partially Matching Zig Enums

#147
post #143

Earlier quoted context omitted.

You might like making and freeing every heap allocation but that doesn't mean it's safer. Every other language would be in the category of 'hidden heap allocations' to a much greater degree. People who understand it don't feel that it is 'spooky'.

I didn't say it was safer, but by "safety" here I don't mean something that will likely work, but an absolute guarantee that it will regardless of what client code does (with the exception of clearly marked unsafe code that's easily found). C++ doesn't offer this kind of safety for pretty much anything. So we're talking about the likelihood of making a mistake - and of not easily finding it - in the absence of safety…

I didn't say it was safer

https://news.ycombinator.com/item?id=44846507

Zig is safer than C++

I copy and pasted what you said.

Re: Partially Matching Zig Enums

#148
post #124

Earlier quoted context omitted.

Fair enough :) I guess one could claim that some feature is useful because it eliminates certain classes of bugs while another is useless because it eliminates certain classes of bugs (which happens to be the more impactful subset of the former class), it's just not a very compelling claim, especially the way you presented it, which is: Something bad happens, say an attacker steals my data. Rust is useful because I c…

Have you noticed how zero is categorically different from the other numbers, even the very small ones? It's an additive identity. No matter how often we sum together zeroes, the answer is still zero and that won't work for other values. Being the additive identity is categorically different, even though it might seem as though zero is just even smaller than a tenth or a millionth, it's different. In (safe) Rust we ca…

> In (safe) Rust we categorically don't have type unsafety

This is very inaccurate. Simple (i.e. non-dependent) types can describe very, very few properties. 99% of correctness properties cannot be described with simple types at all. That is exactly why, from ATS's vantage point, Rust is about as "safe" as Assembly; its types can guarantee almost nothing, while ATS can guarantee virtually everything.

So now the question is, with what little simple types give us (which is still useful), how much are we willing to pay for what confidence in their soundness. After all, Rust doesn't actually give us 100% safety, because we interact with C code etc.. But it does give us some higher confidence than the one given to us by Zig. So now the question is, since we don't have 100% confidence anyway - there are no zeros or ones here, neither on cost nor on the benefit side - how much are we willing to pay for what amount of added confidence?

Some people find the cost of Rust to be worth the added confidence; some don't. There is no binary line here.

> It's OK, the C++ Convener is absolutely convinced of the same line of thinking as you. Surely if they can just keep finding adjustments to make C++ fractionally safer it'll be as safe as Rust.

I'm not interested in making C++ as safe as Rust. For applications programming I use Java, which is somewhat safer than Rust, and for low-level code, I'm much more interested in other correctness properties than just safety. Safety gives me some small portion of the correctness I want, and it's great when that small portion is mostly free, but the bang-for-the-buck that I get from Rust is too low for me. I pay for all this complication in exchange for only guaranteeing no UAF? For that effort, I want a lot more.

Re: Partially Matching Zig Enums

#149
post #141

Earlier quoted context omitted.

> If you don't want memory leaks, it probably is what you want. No, sorry. > A lot of this seems like you haven't done a lot of modern C++ to see how elegant and smooth it is. It's true I don't want to use modern C++ (except for certain compile-time tests), and that's because when I write low-level code what I care about the most is being able to see the machine instructions that will be emitted, especially the ones…

Oooh yeah, sorry no, smart pointers and destructors do prevent memory leaks. You said no then didn't back it up with anything and just went on a tangent of your own personal preferences.

`smart pointers + destructors => no memory leaks` does not entail `no memory leaks => smart pointers + destructors`.

"My solution offers X, therefore, if you want X, you should use my solution" is just a logical fallacy; the conclusion doesn't follow from the premise.

Also, I'm not so sure smart pointers and destructors actually prevent memory leaks. E.g. cycles. You can deal with cycles, but memory leaks due to them are not "prevented" just by the use of smart pointers and destructors.

Java does prevent leaks due to cycles, but it still doesn't prevent leaks due to "forgotten objects", so you get memory leaks in Java, too, even though it has fewer leaks than C++/Rust with GC pointers. So given that you can have fewer leaks than with smart pointers and still not have them completely gone, I wouldn't say that smart pointers "prevent" leaks. But yes, they're one of the ways to reduce them.

Re: Partially Matching Zig Enums

#150
post #143

Earlier quoted context omitted.

I didn't say it was safer, but by "safety" here I don't mean something that will likely work, but an absolute guarantee that it will regardless of what client code does (with the exception of clearly marked unsafe code that's easily found). C++ doesn't offer this kind of safety for pretty much anything. So we're talking about the likelihood of making a mistake - and of not easily finding it - in the absence of safety…

I didn't say it was safer https://news.ycombinator.com/item?id=44846507 Zig is safer than C++ I copy and pasted what you said.

> I copy and pasted what you said.

No, you didn't. You wrote "You might like making and freeing every heap allocation but that doesn't mean it's safer." That is a very different claim (and one I didn't make) than "Zig is safer than C++".

Zig is safer than C++ because it makes some absolute guarantees that C++ doesn't, and C++ doesn't make any absolute guarantees that Zig doesn't. But no memory leaks is not a guarantee that either Zig or C++ make.

Zig and Rust guarantee that all Zig and Rust programs are free of out-of-bounds access (unless they explicitly use syntactically distinct "unsafe" operations). C++ makes no guarantee about all C++ programs that these two other languages don't make.

To what degree that matters is a perfectly fine subject for debate, but that particular thing - again, important or not - is how I (and others) define "safety" (as it pertains to a language), and I made it clear that that's the definition I'm using.

By that definition, memory leaks are not safe in C, C++, Zig, or Rust, but Zig is still safer than C++ because of other properties that are safe in Zig.

Post reply on HN