I was going to say that it's greatly understating the value of the borrow checker. It guarantees no invalid memory accesses. But then it added: > This means that basically the borrow checker can only catch issues at comptime but it will not fix the underlying issue that is developers misunderstanding memory lifetimes or overcomplicated ownership. The compiler can only enforce the rules you’re trying to follow; it can…
> I don't see why CLI tools are special in any respect. Because they don't grow large or need a multi-person team. CLI tools tend to be one & done. In other words, it's saying "Zig, like C, doesn't scale well. Use something else for larger, longer lived codebases." This really comes across in the article's push that Zig treats you like an adult while Rust is a babysitter. This is not unlike the sentiment for Java bac…
Zig feels more practical than Rust for real-world CLI tools
191–200 of 412 posts
Re: Zig feels more practical than Rust for real-world CLI tools
#192Weird that they don’t consider other options, in particular languages with reference counting or garbage collection. Those will not solve all ownership issues, but for immutable objects, they typically do. For short-running CLI tools, garbage collecting languages may even be faster than ones with manual memory management because they may be able to postpone all memory freeing until the program exits.
Re: Zig feels more practical than Rust for real-world CLI tools
#193"All it took was some basic understanding of memory management and a bit of discipline." The words of every C programmer who created a CVE.
Segfaults go brrr. All jokes aside, it doesn’t actually take much discipline to write a small utility that stays memory safe. If you keep allocations simple, check your returns, and clean up properly, you can avoid most pitfalls. The real challenge shows up when the code grows, when inputs are hostile, or when the software has to run for years under every possible edge case. That’s where “just be careful” stops worki…
Re: Zig feels more practical than Rust for real-world CLI tools
#194Earlier quoted context omitted.
As long as the audience accepts the framing that ergonomics doesn't matter because it can't be quantified, the hand-waving exemplified above will confound. "This chair is guaranteed not to collapse out from under you. It might be a little less comfortable and a little heavier, but most athletic people get used to that and don't even notice!" Let's quote the article: > I’d say as it currently stands Rust has poor deve…
> it's a universal tradeoff, that is: Safety is less ergonomic. I'm not sure that that tradeoff is quite so universal. GC'd languages (or even GC'd implementations like Fil-C) are equally or even more memory-safe than Rust but aren't necessarily any less ergonomic. If anything, it's not an uncommon position that GC'd languages are more ergonomic since they don't forbid some useful patterns that are difficult or impos…
Re: Zig feels more practical than Rust for real-world CLI tools
#195The benefit of Zig seems to be that it allows you to keep thinking like a C programmer. That may be great, but to a certain extent it’s also just a question of habit. Seasoned Rust coders don’t spend time fighting the borrow checker - their code is already written in a way that just works. Once you’ve been using Rust for a while, you don’t have to “restructure” your code to please the borrow checker, because you’ve a…
That hasn't been my experience at all. At best, the first version of code pops out quickly and cleanly because the author knows the appropriate idiom to choose. Refactoring rust code to handle changes in that allocation idiom is extremely expensive, even for the most seasoned developers.
Case in point:
> Once you’ve been using Rust for a while, you don’t have to “restructure” your code to please the borrow checker, because you’ve already thought about “oh, these two variables need to be mutated concurrently, so I’ll store them separately”.
Which fails to handle "these two variables didn't need to be mutated concurrently, but now they do".
Re: Zig feels more practical than Rust for real-world CLI tools
#196Earlier quoted context omitted.
What about every Java/JS/Python/Rust/Go programmer who ever created a CVE? Out-of-bounds access is, indeed, a very common cause of dangerous vulnerabilities, but Zig eliminates it to the same extent as Rust. UAF is much lower on the list, to the point that non-memory-safety-related causes easily dominate it.[1] The question is, then, what price in language complexity are you willing to pay to completely avoid the 8th…
Ideally neither Zig nor Rust would matter. Languages like Modula-3 or Oberon would have taken over the world of systems programming. Unfortunately there are too many non-believers for systems programming languages with automatic resource management to take off as they should. Despite everything, kudos to Apple for pushing Swift no matter what, as it seems to be only way for adoption.
Or those languages had other (possibly unrelated) problems that made them less attractive.
I think that in a high-economic-value, competitive activity such as software, it is tenuous to claim that something delivers a significant positive gain and at the same time that that gain is discarded for irrational reasons. I think at least one of these is likely to be false, i.e. either the gain wasn't so substantial or there were other, rational reasons to reject it.
Re: Zig feels more practical than Rust for real-world CLI tools
#197Earlier quoted context omitted.
> thus effectively switching to automatic garbage collection Arc isn't really garbage collection. It's like a reference counted smart pointer like C++ has shared_ptr. If you drop an Arc and it's the last reference to the underlying object, it gets dropped deterministically. Garbage collection generally refers to more complex systems that periodically identify and free unused objects in a less deterministic manner.
That's fair. It's not really a good pattern though. You get all the runtime overhead of object-soup allocation patterns, syntactic noise making it harder to read than even a primitive GC language (including one using ARC by default and implementing deterministic dropping, a pattern most languages grow out of), and the ability to easily leak [0] memory because it's not a fully garbage-collected solution. As a rough ap…
However, I disagree with generalizations that you can judge the quality of code based on whether or not it uses a lot of Arc. You need to understand the architecture and what's being accomplished.
Re: Zig feels more practical than Rust for real-world CLI tools
#198Earlier quoted context omitted.
How did AWS mess up errors?
Maybe I am holding it wrong. Here is one piece of the problem: while let Some(page) = object_stream.next().await { match page { // ListObjectsV2Output Ok(p) => { if let Some(contents) = p.contents { all_objects.extend(contents); } } // SdkError Err(err) => { let raw_response = &err.raw_response(); let service_error = &err.as_service_error(); error!("ListObjectsV2Error: {:?} {:?}", &service_error, &raw_response); retu…
while let Some(page) = object_stream.next().await {
match page {
// ListObjectsV2Output
Ok(p) => {
if let Some(contents) = p.contents {
all_objects.extend(contents);
}
}
// SdkError
Err(err) => {
let raw_response = err.raw_response();
let service_error = err.as_service_error();
error!("ListObjectsV2Error: {:?} {:?}", service_error, raw_response);
return Err(S3Error::Error(format!("ListObjectsV2Error: {:?}", err)));
}
}
}
I would have written it this way while let Some(page) = object_stream.next().await {
let p: ListObjectsV2Output = page.map_err(|err| {
// SdkError
let raw_response = err.raw_response();
let service_error = err.as_service_error();
error!("ListObjectsV2Error: {service_error:?} {raw_response:?}");
S3Error::Error(format!("ListObjectsV2Error: {err:?}"))
})?;
if let Some(contents) = p.contents {
all_objects.extend(contents);
}
}
although if your crate defines `S3Error`, then I would prefer to write while let Some(page) = object_stream.next().await {
if let Some(contents) = page?.contents {
all_objects.extend(contents);
}
}
by implementing `From`: impl From> for S3Error {
fn from(err: SdkError) -> S3Error {
let raw_response = err.raw_response();
let service_error = err.as_service_error();
error!("ListObjectsV2Error: {service_error:?} {raw_response:?}");
S3Error::Error(format!("ListObjectsV2Error: {err:?}"))
}
}Re: Zig feels more practical than Rust for real-world CLI tools
#199Earlier quoted context omitted.
"It's true when you ride a skateboard with a helmet on." Rust is not the helmet. It is not a safety net that only gives you a benefit in rare catastrophic events. Rust is your lane assist. It relieves you from the burden of constant vigilance. A C or C++ programmer that doesn't feel relief when writing Rust has never acquired the mindset that is required to produce safe, secure and reliable code.
No. It is not an invisible safeguard - it yaps and significantly increases compile time and (a matter of great debate) development effort. It is a helmet, just accept it. Helmets are useful.
Re: Zig feels more practical than Rust for real-world CLI tools
#200Earlier quoted context omitted.
> thus effectively switching to automatic garbage collection Arc isn't really garbage collection. It's like a reference counted smart pointer like C++ has shared_ptr. If you drop an Arc and it's the last reference to the underlying object, it gets dropped deterministically. Garbage collection generally refers to more complex systems that periodically identify and free unused objects in a less deterministic manner.
Reference counting has always been a way to garbage collect. Those who like garbage collection have always looked down on it because it cannot handle circular references and is typically slower than the mark and sweep garbage collectors they prefer. If you need a referecne counted garbage collector for more than a tiny minotiry of your code, then Rust was probably the wrong choice of language - use something that has…
However, the difference between Arc and a Garbage Collector is that the Arc does the cleanup at a deterministic point (when the last Arc is dropped) whereas a Garbage Collector is a separate thing that comes along and collects garbage later.
> If you need a referecne counted garbage collector for more than a tiny minotiry of your code
The purpose of Arc isn't to have a garbage collector. It's to provide shared ownership.
There is no reason to avoid Rust if you have an architecture that requires shared ownership of something. These reductionist generalizations are not accurate.
I think a lot of new Rust developers are taught that Arc shouldn't be abused, but they internalize it as "Arc is bad and must be avoided", which isn't true.