It's inspired by Terry Davis who didn't believe in sandboxes and security, he wanted to just run code and write code. It's your responsibility to read the code, :-P
I’ve just read the two functions there by that footnote, `reaching_copies_meet`. I have so much code review feedback just on code style, before we even get into functionality. And it’s like 20 lines. (The function shouldn’t return an error set, it should take an allocator, the input parameter slices should be const, the function shouldn’t return either the input slice or a newly allocated slice.)
It’s interesting how Zig clicked for me pretty quickly (although I have been writing it for a couple of years now). But some of the strategies of ownership and data oriented design I picked up writing JavaScript. Sometimes returning a new slice and sometimes returning the same slice is a problem for memory cleanup, but I wouldn’t do it even in JavaScript because it makes it difficult for the caller to know whether they can mutate the slice safely.
I suspect that there’s a way to write this algorithm without allocating a temporary buffer for each iteration. If I’m right that it’s just intersecting N sets, then I would start by making a copy of the first set, and on each iteration, removing items that don’t appear in the new set. I suspect the author is frustrated that Zig doesn’t have an intersect primitive for arrays, but usually when the Zig standard library doesn’t have something, it’s intentionally pushing you to a different algorithm.
Feels like maybe something lost in translation with their explanation - they say they were fed up of data structures etc. but they returned to Rust? I’m assuming there’s something a bit more nuanced about what they got tired of with Zig
Rust is a world away from Zig as far as being low-level. Rust does not have manual memory management and revolves around RAII which hides a great deal of complexity from you. Moreover it is not unusual for a Rust project to have 300+ dependencies that deal with data structures, synchronization, threading etc. Zig has a rich std lib, but is otherwise very bare and expects you to implement the things you actually want.
This depends on what you mean by low level. Commonly it means, how much you need to take care about minute, low-level issues. In that way C, Rust, and Zig are about the same.
Dependencies have nothing to do with low-level vs. high-level but just package management, how well the language composes, and how rich the standard library is. Are assumptions in package A able to affect package B. In C that's almost impossible to avoid, because different people have different ideas about how long their objects live.
Having a rich standard library isn't just a pure positive. More code means more maintenance.
I agree with you that package management has nothing to do with how low-level a language is.
That being said Rust is definitely a much higher level language than either C or Zig. The availability of `Arc` and `Box`, the existence and reliance on `drop`, and all of `async` are things that just wouldn't exist in Zig and allow Rust programmers to think at higher levels of abstraction when it comes to memory management.
> Having a rich standard library isn't just a pure positive. More code means more maintenance.
I would argue it's much worse to rely on packages that are not in the standard library since its harder to gain trust on maintenance and quality of the code you rely on. I do agree that more code is almost always just more of a burden though.
> That being said Rust is definitely a much higher level language than either C or Zig. The availability of `Arc` and `Box`, the existence and reliance on `drop`
I mean, C++ have RAII and stuff like unique pointer, does that make it higher level than Zig?
And what if you don't use Arc or Box? Is your program now lower level than baseline Rust?
As I said, depends a lot about what you mean by low level.
It depends on the facilities the language offers to you by default right?
C++ offers much higher level primitives out of the box compared to Zig, so I'd say its a higher level language. Of course you can ignore all the features of C++ and just write C, but that's not why people are picking the language.
IMO "level" roughly corresponds to the amount of runtime control flow hidden by abstractions. Zig is famous for having almost no hidden runtime control flow, this appears pretty "low level" to many. OTOH, Zig can have highly non-trivial hidden compile time control flow thanks to comptime reflection, but hardly anyone identifies Zig as a "high level" metaprogramming language.
I'd say so. Zig is aiming to be a bit smarter than C while staying at roughly the same level. C++ more sought/seeks to support C but offer higher level things with it.
And in practice the maintenance just doesn't get done. That's why Python's "rich standard library" with batteries included not only periodically has to throw out "dead batteries" because parts of its stdlib are now obsolete, but also has an ecosystem where good Python programmers don't use parts of the stdlib "everybody knows" just aren't good enough.
You see that in C++ too. The provided hash tables aren't good enough so "everybody knows" to use replacements, the provided regular expression features aren't good enough, there's the 1970s linear algebra library that somebody decided must be part of your stdlib, here's somebody's "my first optimized string buffer" type named string...
For now Zig is young enough that all the bitrot can be excused as "Don't worry, we'll tidy that up before 1.0" but don't rely on that becoming a reality.
I think Rust is "higher level" than C or Zig in the sense that there are most abstractions than C or Zig. Its not Javascript, but it is possible to program Rust without worrying too much about low level concerns.
The languages trade complexity in different areas. Rust tries to prevent a class of problems that appear in almost all languages (i.e two threads mutating the same piece of data at the same time) via a strict type system and borrow checker. Zig won't do any of that but will force you to think about the allocator that you're using, when you need to free memory, the exact composition of your data structures, etc. Depending on the kind of programmer you are you may find one of these more difficult to work with than the other.
There are some cases in Rust where the borrow checker rejects valid programs, in those cases it may be because of a certain data structure in which case you probably have many crates available to solve the issue, or you can solve it yourself with boxing, cloning, or whatever. The vast majority of the time (imo) the borrow checker is just checking invariants you have to otherwise hold and maintain in your head, which is harder and more error prone.
The actual hard part of Rust is dealing with async, especially when building libraries. But thats the cost of a zero-cost async abstraction I suppose.
Then it's actually the immature zig ecosystem that rubbed the author the wrong way, not zig the language itself. Not that the ecosystem isn't important, but IMO a language only truly fails you when it doesn't offer the composability and performance characteristics necessary for your solution.
Not really understanding what this would be though, zig has all the basic stuff you would expect in its stdlib (hashmap, queues, lists etc) just like Rust
While you can obviously write low level code in Rust and manage allocations, memory, use pointers etc, you can also write much higher level code leveraging abstractions both in Rust itself and its' rich ecosystem. If you're coming from higher level languages it's much friendlier than C/C++ or Zig. I think I would struggle to write C or Zig effectively but I have no issues with Rust and I really enjoy the language.
> I do not know if it is me being bored with the project, or annoyed with having to build and design a data structure, that has soured me on this project. But I have really at this point lost most motivation to continue this chapter. The way Zig is designed, it makes me deal with the data structure and memory management complexity head on, and it is tiresome. It is not "simpler" than, say, Rust: it just leaves the programmer to deal with the complexity, <strike-through>gaslighting the user</strike-through> claiming it is absolutely necessary.
c-testsuite is amazing. i use it to test my compiler, but even after passing the test. my compiler still choke on some real world project. also the tests lack many of arcane preprocessor rules. so you still need to read https://www.spinellis.gr/blog/20060626/ in order to understand hideset and its macro expansion algorithm.
I have found portability bugs in many projects with slimcc just because it exposed different preprocessor defines, some gate critical __attribute__ behind __GNUC__ check, some have buggy fallback to __builtin functions or VLA that nobody noticed in years, these could have been avoided with just an automatic build job in the CI with kefir or slimcc, (tcc is awesome but less suited for being a drop-in).
It is also important to have more independent implementations of the C standard, not only to sort out dark corners in the specification (current WG14 have been doing great), but to prevent it turning into GCC-Clang power struggle.
Can't speak for kefir; slimcc has been `make unittest`ing Neovim v0.10.4 with no source modification in a Debian VM (so it's pretty portable, thanks!)
On tcc, the most common dealbreaker is no thread local support, having independent assembler/linker is a wonderful feat but not being feature parity with binutils could lead to build failure, contributors generally less willing to support the correct behavior for ABI, C standards and GCC extensions.
I hope these don't sound like a diss, if I had been better at reading its coding style I would definitely try to contribute to mob branch.
reply