Hacker News new | past | comments | ask | show | jobs | submit | bornfreddy's comments login

Reliable 5% yield while keeping the base the same value (rising with inflation)? Possible, but not without risk. And if you want to protect against that risk, i.e. accept that some investments will fail [0], you need a bigger amount, imho. Or accept that you will get less, not 35k per year.

[0] https://finance.yahoo.com/quote/INTC/


That's a good point. But if I'm realistic with my own mortality I'd be happy if I reached 70.

Assuming I retire at 40, and need to make 700k last 30 years, that's 23k per year with no yield. Even a modest 3% yield slows the burn rate so my money would still outlast me.

Or I'll be 73 writing Python which might not be so bad...


Yeah that's ugly, but it doesn't really matter. What is worse is inconsistencies when declaring class vars and constants... But you learn to live with it.

Go is not an alternative to PHP, and I say this as someone who likes (and uses) Go. It is more performant, yes, but it is also very verbose - I would hate to develop a CRUD (web) app in it. Not to mention that any data handling is more or less manual. Great language for some services, but not for a webapp.

Also PHP is far from slow. The code is precompiled ("cached") and the common operations are optimized as hell. IME the slow apps are usually just missing some MySQL indexes or similar.


PHP is slow, as an example we generate (somewhat complex pdf documents from a sourced html file), and it takes PHP multiple seconds to parse and generate the document. We since rewrote this in Go and now it runs in milliseconds.

This is pure CPU bound (the IO is only opening a file and not a bottleneck) and PHP is still very slow for anything more complex.


Firefox here too, no such problems. I do however run Google services in a separate browser (Brave or Chromium) because most of them hog the Firefox browser. For example running earth.google.com on FF is... a very special experience. :-/

Like Aral Sea? Thanks, I can live without.

VSCode is opensource. Remote ssh agent is not.

VSCode is not if installed with binaries.

Are you saying that the VSCode binaries are not built from the exact source that is available? Or that the opensource license doesn't apply to the version of VSC that is distributed via binaries?

I'm using VSCodium myself anyway, but I'm also installing it from binaries (precompiled packages), as is the case with most opensource software I use.


What's that got to do with anything?

that you can theoritically audit vscode code, but not ssh agent code...

Does that have anything to do with SECURITY?

The train of logic has run way off the rail in this thread.


I wanted to like Rust (memory safety and performance - what's not to like?) but both of my experiments with it ended in frustration. It seemed a way too complex language for what I needed.

Recently, a coworker of mine made a great observation that made everything clear to me. I was looking for a replacement for C, but Rust is actually a replacement for C++. Totally different beast - powerful but complex. I need to see if Zig is any closer to C in spirit.


> I was looking for a replacement for C, but Rust is actually a replacement for C++. Totally different beast - powerful but complex.

I've seen this sentiment a lot, and I have to say it's always puzzled me. The difference between Rust and basically any other popular language is that the former has memory safety without GC†. The difference between C++ and C is that the former is a large multi-paradigm language, while the latter is a minimalist language. These are completely different axes.

There is no corresponding popular replacement for C that's more minimalist than Rust and memory safe.

† Reference counting is a form of garbage collection.


Board games and craft beers are utterly unrelated objects who have commonality on essentially no axes (except sitting on tables, I guess). And, yet, if you like one, there's a very good chance you like the other.

I think that's where the sentiment comes from. It's not that Rust is similar to C++ in terms of the actual languages and their features. It's that people who like C++ are morely likely to like Rust than people who like C are.

I would argue that C is not a minimalistic language either. There is a lot under the hood in C. But it feels small in a way that Rust and C++ don't.

I think Rust and C++ appeal to programmers who are OK with a large investment in wrapping their head around a big complex language with the expectation that they will be able to amortize that investment by being very productive in large projects over a large period of time. Maybe sometimes the language feels like trying to keep a piece of heavy duty machinery from killing you, but they're willing to wrestle with it for the power you get in return.

The people who are excited about Zig and C wants something that feels more like a hand tool that doesn't demand a lot of their attention and lets them focus on writing their code, even if the writing process is a little more manual labor in return.


> And, yet, if you like one, there's a very good chance you like the other.

Among my friends I know several people who are very enthusiastic about board games and several who are very enthusiastic about craft beer, but there's not a particular noticeable overlap. Personally of course I am very into board games and I don't drink at all.

> I would argue that C is not a minimalistic language either. There is a lot under the hood in C.

Nah, C actually is small, that's why K&R is such a short book. It makes enormous compromises to pull that off, but presumably on a machine where 64kB of RAM is extraordinary these compromises made lots of sense. C23 is quite a bit bigger, for example "bool" is now an actual type (albeit implicitly convertible) but still small by modern standards.

There really isn't that much "under the hood", it's often just the least possible moving parts that could possibly have worked.

a[b] in C++ is a call to a member function a.operator[](b) -- arbitrary user code

a[b] in Rust is a call to core::ops::Index::index(a, b) or, in context IndexMut::index_mut -- again, arbitrary user code

a[b] in C is just a pointer addition of a and b - one of them will be converted to a pointer if necessary, and then the other one is added to the pointer using normal pointer arithmetic rules


> Nah, C actually is small,

I'd argue that C is much bigger than K&R, but that isn't immediately visible to a new programmer because it's all undefined behaviors.


C23 + compiler extensions versus K&R C, is a little more than only UB.

Except C in 2025 isn't K&R C, rather C23.

Also even between C89 and C23, many folks wrongly count "whatever my compiler does" as C, and there are endless amounts of extensions to be aware of.


Exactly. There are two kinds of programmers, those who enjoy spending a bunch of time thinking about problems and decisions the language has foisted upon you (subtyping hierarchies, lifetime annotations, visibility, design patterns) and there are those that like spending that time thinking about the actual problem they want to solve instead.

I jest, but only a tiny bit. The features of heavy OOP and feature-rich languages tend to show their value only in really large codebases being worked on by several different people—precisely because many of their features are just guardrails to make it hard for people to code incorrectly against another's understanding or assumptions, when shared understanding is more difficult to establish. Contrarily, any solo programmer or really small team is almost invariably better served by a language like go, C, scheme, or Zig.


The idea that memory safety is only, or primarily, a problem in large codebases written by a sizable team is an interesting theory (sort of an inverse Linus' Law?) Unfortunately, it's contradicted by decades of experience.

Just to be clear, I liked memory handling in Rust. It was the sheer size of the language that made it... not fun. But borrow checker made sense.

Go is pretty good for large, shared projects too - thanks to its tooling, formalized best-practices and comprehensive batteries-included standard library.

That is simply not true. The bigger the project gets the more you see the shortcomings of go. You can see that very well in the k8s project

Ok, might want to explicitly point out those shortcomings that still present today. AFAK such shortcomings resulting in issues have been fixed in Go over the years.

Partially fixed within the backwards compatibility Go 1.0 promise.

> Maybe sometimes the language feels like trying to keep a piece of heavy duty machinery from killing you, but they're willing to wrestle with it for the power you get in return.

It's funny because to me there's an analogy with heavy machinery but materially different: there are some industrial machines that have two buttons that need to be actuated to activate the mechanism, separated by arm length in order to ensure that the operator's arms are out of the way when the limb crunching bits are moving. I see Rust that way, engineering the safe way to do things as the path of least resistance, at the cost of some convenience when trying to do something "unsafe".


Okay, but now imagine a kitchen appliance that did the same thing. It would not be a big seller. Of course a kitchen appliance can injure and even kill you, but it probably wouldn’t unless you try really hard.

Most of programming is like that, but in the few cases where there literally are lives at stake, memory safety by itself will not do much for you and performance is going to be a secondary concern.

Zig does have safety features that C/C++ do not have, but also one should not underestimate the security implications of language complexity by itself.


The reason I focus on the memory safety difference is precisely to not minimize its importance. It's far more salient of a difference than whether a language "feels big" or not. Talking about whether Zig requires "a little more manual labor" than Rust is missing the enormous elephant in the room.

I think the people who like Rust are in a room where they perceive that elephant to be enormous and people who like Zig are in a room where they perceive it to be much smaller.

You can certainly argue whether or not their perceptions are correct, but I generally believe that people are entitled to their priorities.

Either way, you initially stated confusion about why people stated certain opinions about Rust, C++, and C. I tried to explain why people might hold those opinins. You are then arguing that they shouldn't hold those opinions. Whether or not that's true, a prescriptive claim is orthogonal to understanding what's actually in their heads.


The elephant is enormous, because the C crowd is not living up to what they need to do to actually make the lack of memory unsafety unimportant. C is like ruby in the sense that the untyped nature of ruby might initially buy you a productivity win, but in the long run it requires you to dilligently write impeccable unit tests, since even the most basic correctness checks can only be done at runtime.

Actually that's wrong. In C you will need exhaustive formal verification, because UB doesn't cause minor miscompilation anymore. Formal verification is far more onerous than whatever Rust is demanding.


> It's far more salient of a difference than whether a language "feels big" or not.

You clearly don't like it, but it seems many people disagree.


pcwalton is responsible for a lot of the rust borrow checker, so, not a neutral opinion. ive posted it too many times on this thread but it seems borrow checking analysis may be possible for zig (if the zig team should want to)

I highly suspect it won't be feasible for the same reason it isn't feasible in C++: you could technically implement it, but tons of existing patterns in the ecosystem would become impossible to express, so in practice it would end up creating a different language. From a skim, the CLR project you linked to claims that metadata will probably be needed in order to enforce aliasable xor mutable, and I agree.

> tons of existing patterns in the [C/C++] ecosystem would become impossible to express

Well, the really harsh way of putting this is that the patterns break for a reason; they rely on global claims about the program, so they aren't genuinely robust in the context of code that sits within a large, constantly evolving codebase that can't be practically surveyed in its entirety. Rust is very good at picking patterns that can be verified with a comparatively straightforward, "local" analysis that broadly follows the same structure as the actual program syntax. Safety claims that rely on "global" properties which cannot be kept within a self-contained, module-like portion of the code are essentially what the unsafe marker is intended for. And this is exactly what idiomatic C/C++ code often gives you.

This is actually why I think that proposals like Safe C++ should get a lot more attention that they do at present. Yes, Safe C++ changes what's idiomatic in the language but it does so in a way that's broadly sensible (given our increased attention to memory safety) especially in a context of "programming in the large".


you can go a long way before getting to aliasable xor mutable, and the metadata doesn't require a language change, theres an example in there on how to bind metadata with no language changes.

Today all of the code I'm not paid to write is in Rust. I spent many happy years previously getting paid to write C (I have also been paid to write Java, PHP, Go and C#, and I have written probably a dozen more languages for one reason or another over the years but never as specifically a thing people were paying me to do)

I always thought C++ was a terrible idea, from way before C++ 98, I own Stroustrup's terrible book about his language, which I picked up at the same time as the revised K&R and it did nothing to change that belief, nor have subsequent standards.

However, I do have some sympathy for this sentiment about Rust being a better C++. Even though Rust and C++ have an entirely different approach to many important problems the syntax often looks similar and I think Zig manages to be less intimidating than Rust for that reason if you don't want that complexity.

Personally I had no interest in C++† and I have no serious interest in Zig.

† Ironically I ended up caring a lot more about C++ after I learned Rust, and most specifically when understanding how Rust's HashMap type works, but I didn't end up liking C++ I just ended up much better informed about it.


It is not about memory safety or anything like that. It is about simplicity.

If you say "you can't do x with y in C++" you will get an "yes you can, you just use asd::dsadasd::asdadqwreqsdwerig_hfdoigbhiohrf() with weaorgoiawr flag". From what I have seen from Rust, it is similar. I don't want to fill my brain with vim bindings.. cough.. Rust ways of doing something. I just want to code my hobby game engine v7.

That said, I am happy to use software written in it. Even though the evangelists can be really annoying.


> † Reference counting is a form of garbage collection.

I agree with Raymond Chen's take on the academic definition of GCs[1], and therefore Rust is certainly a GC'd language (because your code behaves as though memory is infinite... usually). It's probably one of the first examples of "static garbage collection" - though I'm sure someone will point out a prior example.

[1]: https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13...


This feels like deliberate misdirection, because in most practical cases what people mean is "some memory management process that will slow my program down non-trivially". By this definition Rust does not have GC whereas Go, eg, does.

The "simulates infinite RAM" is an interesting perspective but simply not the subject of most conversations.


Manual heap allocation can slow the program down non-trivially compared to using an arena which is cleaned up all at once; hence, manual heap allocation is a kind of GC. Checkmate atheists.

>Manual heap allocation can slow the program down non-trivially compared to using an arena

But GC has nothing to do with whether heap allocations 'slow the program down', it's who owns the lifetime of the allocated object - for GC not the programmer, but the runtime.

If I create a an object, and then then soon after deref it [MyObj release], then I know it will dealloc immediately after. I'm basically in control of its lifetime, even though it's ref counted.

If I call [MyObj free] and it's still owned by another object (e.g. I added it to some collection), that's OK because the object is still useful and has a lifetime outside of my control, and its destruction will be deferred until it doesn't.

But, with a GC object, if I call new MyObj() and then soon after try my best to destroy it, I can't because I'm not in control of its lifetime, the runtime is.

That's what I see the distinction between GC and ref counted (not GC), and why I mostly don't agree with so many people here insisting that ref counting is garbage collection. How can it be when I can easily be explicitly in control of an objects lifetime? I create it, then I destroy it, and it happens exactly in the sequence that I dictate.

For sure, ARC makes it a bit more subtle, but even then, I can reliably predict when an object will be destroyed and factor that into the sequence of events in my program.

-An Atheist.


I went down a path researching the viability of region based memory management (a form of arenas).

A language based on such a paradigm can be provably memory safe, and regions can have their own allocators and optionally provide locking when the regions are shared.

This approach obviates the need for reference counting individual allocations (since regions are tracked as a whole), but it suffers from excess memory usage in the event of many short-lived allocations (i.e. they leak until the entire region's allocations go out of scope). But those types of memory accesses can be problematic in every systems language as they can eventually cause memory fragmentation.

That problem can be minimized using per-allocation reference counting, but that can incur a heavy performance hit. Although not having to use it everywhere could minimize the impact.

The plus side is you don't have to worry about borrow checking, so such a language can be more flexible than Rust, while still maintaining the memory safety aspect.

The question, as always, is: is the juice worth the squeeze?

Truthfully, I suspect no. The Rust train has left the station and has a decade head start. Even if it is a pain in the ass, lol.


What’s old is new again. Cyclone, one of the influences on Rust, is a systems language using regions for memory management.

You may be interested in Rust language proposals for local memory allocators and "storages"; they may be enough for something very much like this. The lifetime concept in Rust is quite close already to that of a "region", i.e. an area of memory that the lifetime can pertain to.

Depending on the semantics of the implementation, something like that would go a long way toward eliminating one of my biggest issues with Rust. For a low-level systems language, it is imperative to offer 2 things, which are currently a pain in Rust: (1) you must be able to "materialize" a struct at an arbitrary location; why? Because hardware tables exist at a specified location and are provided by hardware- they are not created or instantiated in the host language; and (2) be able to reference structs from other structs, which immediately triggers lifetime annotations, which begin to color everything they touch, must like async does to functions.

And I admit, I loathe the borrow checker. Ironically, I never really have problems with it, because I do understand it, it's just that I find it too limiting. Not everything I want to do is unsafe, and I hate the way it has made people think that if you really do know better than the borrow checker, you must clearly be doing something wrong and you should re-architect your code. It's insulting.


GC is bad because of memory fragmentation due to pointer aliasing. (Not GC pauses per se.)

Theoretically you could have a GC'd language that cared about scope, lifetimes, stack vs heap and value vs reference distinctions, but no such thing was ever seen in the wild. (Perhaps because people use GC'd languages precisely because they don't want to care about these distinctions.)


By that definition, a C++ program with heavy usage of std::shared_ptr has GC.

And it does. Reference counting is garbage collection. And std::shared_ptr, or Rust's Rc/Arc are basically lightweight GC runtimes inside your program.

Isn't that the point?

I don't think it's the point of the comment I replied to, no.

By this logic you're writing the garbage collector by hand in C.

> There is no corresponding popular replacement for C that's more minimalist than Rust and memory safe.

In the real world, memory safety is not all-or-nothing (unless you're willing to concede that Rust is not safe either, since unsafe Rust exists). I'm working on an embedded project in Rust and I'd MUCH rather be using Zig. The only safety thing that Rust would give me that Zig does not is protection from returning pointers to stack-allocated objects (there are no dynamic allocations and no concurrency outside of extremely simple ISRs that push events onto a statically allocated queue). But in exchange I have to deal with the presence of unsafe Rust, which feels like a gigantic minefield even compared to C.


protection from returning stack pointers seems to be detectable with static analysis of zig AIR.

https://github.com/ityonemo/clr


> But in exchange I have to deal with the presence of unsafe Rust, which feels like a gigantic minefield even compared to C.

I think idiomatic coding norms for unsafe Rust are still a bit half-baked, and this is where something like Zig can have an advantage of sorts. You can see this also, e.g. in the ongoing proposals for a Pin<> alternative.


The similarity between C++ and Rust is that both bust your balls with complexity for programming at large. And the inverse goes for C and Zig.

Those are the axes relevant to the parent in the context of their comment - not specific language semantics or core features.


> > I was looking for a replacement for C, but Rust is actually a replacement for C++. Totally different beast - powerful but complex.

> The difference between Rust and basically any other popular language is that the former has memory safety without GC†. The difference between C++ and C is that the former is a large multi-paradigm language, while the latter is a minimalist language. These are completely different axes.

Indeed. Let one axis be the simple/multi paradigm. Let the other axis be no memory management / automatic memory management without GC / GC. This divides the plane into 6. In the simple + no memory management sits C and Zig, and in the multiparadigm + memory safe without GC segment sits C++ and Rust.

> There is no corresponding popular replacement for C that's more minimalist than Rust and memory safe.

Those are some weird requirements for "being a replacement", but it is obviously true, as you picked them such.


It's not a perfect analogy, but if you want to put yourself in the shoes of the people making it:

1. Rust is an immensely complicated language, and it's not very composable (see the async debacle and whatnot). On the simple<->complex slider, it's smack dab on the right of the scale.

2. Ignoring any nitpicking [0], Zig is memory-safe enough in practice, placing it much closer to Rust than to C/C++ on the memory safety axis. My teammates have been using Zig for nearly a year, and the only memory safety bug was (a) caught before prod and (b) not something Rust's features would have prevented [1]. The `defer` and `errdefer` statements are excellent, and much like how you closely audit the use of `unsafe` in Rust there is only a small subset of Zig where you actually need to pull your magnifying glass out to figure out if the code has any major issues. In terms of memory issues I've cared about (not all conforming to Rust's narrow definition of memory safety), I've personally seen many more problems in Rust projects I contribute toward (only the one in Zig, plus a misunderstanding of async as I was learning the language a few years ago, many of varying severity in Rust, at this point probably more code written in Zig than Rust, 10yoe before starting with either).

With that in mind, you have C/C++ on the unsafe axis and Zig/Rust on the safe axis. The complexity axis is self-explanatory, fleshing out the analogy.

Is Zig memory-safe? No, absolutely not. Does that mean that Rust will win out for some domains? Absolutely. In practical terms though, your average senior developer will have many memory safety bugs in C/C++ and few in Zig/Rust. It's a reasonable way to compare and contrast languages.

Is it a perfect description? No, the map is not the territory. It's an analogy that helps a lot of people understand the world around them though.

[0] Even Python is simpler than Rust, and it's memory-safe. If we're limiting ourselves to systems languages, you still have a number of options like Ada and Coq. Rust is popular because it offers a certain tradeoff in the safety/performance/devex Pareto curve, and because it's had a lot of marketing. It's unique in that niche, by definition, but it's far from the only language to offer the features you explicitly stated.

[1] It was just an object pool, and the (aggregate) resetting logic wasn't solid. The objects would have passed through the borrow checker with flying colors though.

Edit: To your GC point, many parts of Rust look closer to GC than not under the hood. You don't have a GC pause, but you have object pools (sometimes falling back to kernel object pools) and a variety of allocation data structures. If RC is a GC tactic, the extra pointer increment/decrement is negligible compared to what Rust actually does to handle its objects (RC is everything Rust does, plus a counter). That's one of my primary performance complaints with the language, that interacting with a churn of small objects is both expensive and the easiest way to code. I can't trust code I see in the wild to behave reasonably by default.


> see the async debacle and whatnot

The async featureset in Rust is far from complete, but async is also somewhat of a niche. You're not necessarily expected to use it, often you can just use threads.

> Zig is memory-safe enough in practice

Temporal safety is a huge deal, especially for the "programming in the large" case. Where unstated assumptions that are relied upon for the safety of some piece of code can be broken as some other part of the code evolves. The Rust borrow checker is great for surfacing these issues, and has very few practical alternatives.

> If we're limiting ourselves to systems languages, you still have a number of options like Ada and Coq.

It's easy to be "safe" if the equivalent to free() is marked as part of the unsafe subset, as with Ada. Coq is not very relevant on its own, though I suppose it could be part of a solution for proving the memory safety of C code. But this is known to be quite hard unless you do take your care to write the program in the "idiomatically safe" style that a language like Rust points you to.


> The async featureset in Rust is far from complete, but async is also somewhat of a niche. You're not necessarily expected to use it, often you can just use threads.

I’m sorry but it’s not true. You lose access to most of the ecosystem.


I've been seeing C++ fans talk about how they never see memory safety issues in practice in C++ for a decade and a half. I even believed it sometimes. But if there's ever been a common story over those 15 years, it's that these anecdotes mean little, and the actual memory safety property means a lot.

The only time I've seen "almost memory safe" actually work is in Go and Swift, which have memory safety problems with concurrency, but they're actually rare enough not to matter too much (though in Go's case it would have been easy to design interfaces and slices not to have the problem, and I wish they had). I simply don't believe that Zig is meaningfully more memory safe than C++.


I don't see any Zig repositories under https://github.com/pcwalton

Is your opinion based on anything other than pure speculation?

I think it makes more sense to form an opinion after actually having tried Rust, C++, and Zig in earnest.

There are lots of us out there who've done it. Join us!


I think it's possible to retrofit race-safe slices and interfaces into Go, and I expect it to happen one day once some actually relevant code execution exploit shows up.

There's going to be some impact and low-level libraries that manipulate directly the words that constitute slices and interfaces, and there will some slight performance impact and increase in memory usage, but hopefully nothing drastic.


I think slices and interfaces in Go are both 2×usize width, in which case you just need double-width CAS to make them safe from data races - which most modern architectures support.

Slices are base pointer, length, and capacity, so three words. But there's a garbage collector, so you can install a thunk if the slice is updated in a way that torn reads cause problems. It makes reads slightly slower, of course.

Two-word loads could be used for interface values (assuming that alignment is increased), except if support older x86-64 is needed. There are implementations that require using CMPXCHG16B, which is a really slow way to load two words. Both Intel and AMD updated their ISA manuals that using VMOVDQA etc. is fine (once the CPU supports AVX and the memory is cacheable).


>"I've been seeing C++ fans talk about how they never see memory safety issues in practice in C++ for a decade and a half. I even believed it sometimes. But if there's ever been a common story over those 15 years, it's that these anecdotes mean little, and the actual memory safety property means a lot."

While I use C++ a lot I am not a fan. It is just one of many languages I use. But from my personal experience it is true. I frankly forgot when was the last time I hit memory problem, years for sure. And my code is often a stateful multithreaded backends with high request rate.


Are you properly trying to exploit your own software?

If you're not looking, how would you know?

You could have a blatant SQL injection in your code and you can always pretend that it doesn't matter, since you haven't been attacked so far.


Memory safety issues show up all the time outside of security exploits. Industry began pursuing memory safety long before anyone cared much about security, simply because of the productivity impact of chasing down memory leaks and use-after-free bugs. So if they've used C++ for years without having to do that, its pretty meaningful. It also matches my experience working on a large C++ application that had ubiquitous use of smart pointers. I wouldn't want to do that again, but RAII takes you a long way.

>"You could have a blatant SQL injection in your code"

I my case SQL injection is not possible. I am not constructing any SQL statements from input.

>"you can always pretend"

I think it is you pretending to know problems that do not exist in my code.


> On the simple<->complex slider, it's smack dab on the right of the scale.

Sure, but now you snuck in an Artifact of Death (in TvTropes sense) into your codebase. It won't kill your code base immediately and with proper handling it might work, but all it takes is one mistake, one oversight, for it to cause issues.


I agreed with you either way, but I'm currently at a loss as to whether this is a for/against take on rust.

You traded ease of writing for ease of long term ease of debugging, I don't think we agree.

> 1. Rust is an immensely complicated language, and it's not very composable.

It is a procedural language and as such, composition of functions is not implemented easily, if at all possible. It is a shame for sure that such powerful techniques are not possible in Rust, but for some people it is worth the trade off.


It is implemented. But it requires quite a bit of boilerplate if you want to compose arbitrary closures at runtime (as you would in most FP languages), because that involves non-trivial overhead and Rust surfaces it in the code (see "dyn Fn trait objects" for how that works in detail).

Yes i know, i have wrote some FnMut closures muself. I meant, function composition should work like Lisp or Haskell, it should be very easy and intuitive, no boilerplate also. Closures in Rust, feel a lot like a hack compared to functional languages.

The way i put it, is that Haskell is a language with very strict type system, while Rust has very strict type system, and strict scoping. Strict scopes mean that an Fn closure has to be different from a FnMut closure, which also means several other complications when it comes to async.

This trade off is fine with me, but for several other people it doesn't worth it.


There's additional boilerplate involved if you want your closures to keep their captured variables around beyond their original scope in the program; in Rust, that's implemented as a kind of shared ownership which involves Rc<> or Arc<>. FP languages rely on program-wide GC for this, which of course has significant overhead of its own.

Closures are definitely cumbersome in Rust, and Lisp/Haskell/Scala programmers use them all the time. In SICP for example, they translate several math equations to code using higher order functions and closures, and it is wonderful how clean the code is, and how close to the actual mathematics.

That's what i meant it is impossible to do in Rust. From that point of view, Rust is a low level procedural language, but expressing any kind of business logic it is almost as high level as Haskell or Java.

But if we focus on error detection, then Rust is the highest level of any other PL. For example Java or Python are too low level when an error occurs. That high level of error detection is paid of course, and that is by longer compilation times.

If i had a wish though, i would wish Rust had as good closures as Haskell or Lisp.


In principle you could fix any lack of syntactic sugar (which is what leads to the "clean code" feel in Scheme or Haskell - but even Swift has custom sugar of its own for refcounting and copy-on-write) with a custom macro - which would be entirely optional, triggered by a custom attribute such as #[sloppy_code]. But that still requires a lot of fiddly implementation work.

even so it seems like it would eventually be possible to do more safety analysis for zig, if not in the compiler itself:

https://github.com/ityonemo/clr


> There is no corresponding popular replacement for C that's more minimalist than Rust and memory safe.

There is Objective-C, it fits your definition of memory safety.


Objective-C and Swift are the reason why I added the footnote. (Also Objective-C is very, very much not memory safe.)

From what I understand that language is Zig, no?

Also, there's FORTH!


I don't think Zig is memory safe?

Zig is not memory safe. It's one of those "can be more safe than C" modern alternative languages. This includes those various C/C++ alternatives that use a GC or optional one (that users can disable), to provide or increase memory safety. Some of the confusion and drama surrounding Zig, appears to be the vain attempt of marketing it as "safer" than "unsafe Rust". The questionable marketing tactic has sparked numerous arguments and debates.

I was replying to this bit

> difference between C++ and C is that the former is a large multi-paradigm language, while the latter is a minimalist language. These are completely different axes. > There is no corresponding popular replacement for C that's more minimalist than Rust and memory safe.

Edit: oh, I never read the last bit "and memory safe" -- well ya, that's kind of rust's major advantage.


This is actually accurate. While Rust is a great replacement for C, so is C++. But Rust has tons of extra features that C doesn't have, just like C++. Moving from C++ to Rust is a sideways move. Moving from C to Rust is definitely an increase in complexity and abstraction.

Rust is a great replacement for C++ as it fits into the same place in the stack of tools.

Go is not a C or Python replacement.

Zig is a good replacement for C.


> Go is not a C or Python replacement.

Google stopped writing new Python, because they found that the same engineers would produce software with similar defect rates, at a similar price and in similar time, with Go, but it would have markedly better performance, so, no more Python.

Go manages to have a nice sharp start, which means there are going to be a bunch of cases where you didn't need all the perf from C, but you did need a prompt start, so, Java was not an option but Go is fine.

In my own practice, Rust entirely replaces C, which has previously been my preferred language for many use cases.


> But Rust has tons of extra features that C doesn't have, just like C++.

C++ has tons of extra features over C because it's a kitchen sink language. Rust has some extra features over C because in order to support static analysis for memory safety in a practically usable manner, you need those features. In practice, there are lots of C++ features that Rust doesn't bother with, especially around templates. (Rust just has a more general macro feature instead. The C++ folks are now on track to adding a clunky "metaclass" feature which is a lot like Rust macros.)


Every language becomes a kitchen sink with enough time on the market, even C, people really should learn about the standard and the myriad of compiler extensions, K&R C was almost 60 years ago.

C++ already has almost Rust macros, with a mix of compile time execution, concepts and traits, without requiring another mini-language, or an external crate (syn).


> Every language becomes a kitchen sink with enough time on the market,

Sometimes they remove stuff, and then everything written before a specific date stop working.


I've used Rust quite a bit now and there are too many features. It can't claim to be tidy anymore. Sure it's a better situation than C++, but it is getting worse and unlikely to get better.

> Moving from C++ to Rust is a sideways move.

In what sense? Features or complexity? From a productivity/correctness perspective, Rust is a huge step up over C++.


While I agree, that isn't much the case for those using static analysis, and hardened runtimes, which provide much of the same safety improvements, granted without lifetimes tracking.

Use more xcode, Clion, Visual Studio, C++ Builder, and less vi and Emacs for C and C++.

Not everyone has the RIIR luxury for what we do.


Those things certainly help, but as someone who actively maintains a lot of C++, I'll stand by my claim that even with those added tools, Rust is a very large upgrade in both productivity and correctness. I'm not claiming all C++ should be RIIR. But you won't find me starting any new projects in C++, unless compelled to do so.

It is, provided there are crates available for what the assignment is supposed to be.

However C++ folks aren't standing still, and anyone pointing out to cargo, and not using conan/vcpkg, alongside a C++ aware IDE, is doing themselves a disservice, better be 85% there than none at all.


> Zig is a good replacement for C.

I have never used zig, although I have looked into it. I have used C and C++ for a long time, and would like a replacement for C.

To my mind zig is nowhere near a good replacement for C. It adds way too much extra stuff (e.g. metaprogramming). A good replacement for C would have a similar simplicity and scope to C (i.e. a portable assembler) but address known issues. For example it should fix the operator precedence rules to be sane. It should close-off on undefined behavior and specify things more formally than C, and still allow low-level memory manipulation. To be even better than C it should allow stuff that would be obviously correct in assembler, but is UB or ID in C.


Go has plenty of bad design decisions, but not being a safer C isn't one of them.

TinyGo and TamaGo folks enjoy writing their bare metal applications on embedded and firmware.


Somewhat related, even when I work with C++ I use it as "C with RAII". What I actually want is a scheme (R5RS) with manual memory management and a borrow checker. I don't know how well such a monstrosity would actually work in practice, but it's what I've convinced myself that I want.



>"but Rust is actually a replacement for C++. "

I would disagree. C++ provides way more features than Rust and to me Rust feels way more constrained comparatively.


Sure, in the sense that in C++ they've got the Head Of Vecna: https://rpgmuseum.fandom.com/wiki/The_Head_of_Vecna

Many of my favourite Rust features aren't in C++. For example they don't have real Sum types, they don't have the correct move semantic, they are statement oriented rather than expression oriented and their language lacks decent built-in tooling.

But also, some of the things C++ does have are just bad and won't get fixed/ removed because they're popular. And there's no sign of it slowing down.

I think that in practice you should use Rust in most places that C++ is used today, while some of the remainder should be WUFFS, or something entirely different.


>"I think that in practice you should use Rust"

I am doing fine. Thank you. Also I am not a language warrior. I do have my preferences but use many since I am an independent and work with many clients.


The biggest issue for me, is that Rust isn't used where I care about, mainstream language runtimes, compiler toolchains, and GPU ecosystem standards.

No one from them would accept a patch in Rust instead of C or C++.

Yes I know about Deno, but even them haven't rewriten V8, and wgpu or Rust CUDA aren't the same as what Khronos, NVidia, AMD, Microsoft put out in C++.


> Rust is actually a replacement for C++

Last I checked, rust touted itself as a systems programming language, which C++ kinda is but mostly isn't (many C++ features just aren't appropriate or are poorly suited for systems programming).

I would never choose Rust over C++ for scientific programming, because Rust metaprogramming features are so poor.

However I'd probably choose Rust over C in many areas where C is best suited.

So to me the venn diagram of utility shows Rust to overlap with C far more than C++.


I read a blog that called Rust a language that was aimed to be high-level but without GC.

My experience with Zig is that it's also a plausible replacement for C++

explanation needed, bro.

nerdy langnoob or noobie langnerd here. not sure which is which, cuz my parsing skills are nearly zilch. ;)


Zig’s comptime feature gives a lot of the power of C++ templates. This makes it easier to implement a lot of libraries which are just a pain to do in plain C. Even seemingly simple things like a generic vector are annoying to do in C, unless you abandon type safety and just start passing pointers to void.

I believe Zig even has some libraries for doing more exotic things easily, such as converting between an array of structs and a struct of arrays (and back).


>Zig’s comptime feature gives a lot of the power of C++ templates. This makes it easier to implement a lot of libraries which are just a pain to do in plain C. Even seemingly simple things like a generic vector are annoying to do in C, unless you abandon type safety and just start passing pointers to void.

I get it, thanks. in C you have to cast everything to (void *) to do things like a generic vector.

>I believe Zig even has some libraries for doing more exotic things easily, such as converting between an array of structs and a struct of arrays (and back).

yes, iirc, there was a zig thread about this on hn recently.


Depends on which C++ version you're talking about.

C programmers have long suffered the cumbersome ritual of struct manipulation—resorting to C++ merely to dress up structs as classes.

Zig shatters that with comptime and the 'type' type.


jay. eff. cee.

the prejudice and preconceived notions of some of these hn frigtards would be amazing, if it was not known in advance, for a long time now, by me and many others around here, who have more maturity and sense, and who don't have insecurity chips on their shoulders.

i mean, downvoting a perfectly innocuous comment. maybe due to use of the words nerd or noob, even though applied by me to myself, triggers their atavistic, dumbfuck response?

it's good that more sensible people like chongli, pjmlp (old standby here, and usually interesting to read his proglang comments) and infamouscow, are around here (referring to this subthread), otherwise this site would not be worth visiting at all. I, and many others probably, only stick around here, for the relatively rare better threads, that are worth checking out.

as amy hoy of stacking the bricks famously said, fuck hn. it's only optional, not part of my daily tech / biz fix (any more), and i am actively looking out for other, better places to hang out online, to read comments by, and chat with, more sensible people.

https://stackingthebricks.com/


Possibly your GP comment came across as a snarky attack because of the first sentence. It's clear that you didn't mean it that way, but there isn't enough information in "explanation needed, bro" to disambiguate your intent (https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...).

saw this just now.

will reply in a day or two after reviewing my own comments, yours, and your link.


Try to install your own patch for RDRAND and check that it is returning 4? Of course, getting 4 multiple times doesn't mean you have succeeded [0].

[0] https://duckduckgo.com/?q=dilbert+random+generator+nine+nine... (couldn't find a good link to the comic)


The exploit doesn't work in a VM.

This is the best solution - if you don't need persistent storage. I prefer N100 minipcs for this reason - the Minix Z100 I have uses 6.4W at the wall (linux, idle, wifi and bt disabled) and while this is probably more than rpi, I got a silent computer with a case and NVME out of the box. Being in x86-land is just an added bonus.

My rpi4 cost me way too many sd cards.


There is OpenSnitch [0] on Linux, but it us a bit clumsy to setup. I tried it once and didn't get far, but have it again on my todo list. Not aware of something else on Linux.

On Android there is NetGuard [1] which is awesome (not affiliated, just a happy customer).

[0] https://github.com/evilsocket/opensnitch

[1] https://netguard.me/


My only gripe with Netguard is that it screws up roaming. With that enabled I couldn't access apps like my bank and various others when I was out of the country. Other than that, amazing piece of software.

There's a couple of options in settings worth checking, as Netguard works for me when roaming just fine.

Under Settings > Defaults, make sure you don't have "block roaming" turned on.

Expand the rules for the apps giving you issues, and check "Block roaming" isn't ticked for them.


Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: