frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

ESA's Moonlight programme: Pioneering the path for lunar exploration

https://www.esa.int/Applications/Connectivity_and_Secure_Communications/ESA_s_Moonlight_programme_Pioneering_the_path_for_lunar_exploration
25•nullhole•2d ago•4 comments

Wttr: Console-oriented weather forecast service

https://github.com/chubin/wttr.in
94•saikatsg•4h ago•44 comments

“Reading Rainbow” was created to combat summer reading slumps

https://www.smithsonianmag.com/smithsonian-institution/to-combat-summer-reading-slumps-this-timeless-childrens-television-show-tried-to-bridge-the-literacy-gap-with-the-magic-of-stories-180986984/
181•arbesman•9h ago•73 comments

Ex-Waymo engineers launch Bedrock Robotics to automate construction

https://techcrunch.com/2025/07/16/ex-waymo-engineers-launch-bedrock-robotics-with-80m-to-automate-construction/
346•boulos•17h ago•253 comments

FOSS4G Europe 2025 Live Streaming

https://2025.europe.foss4g.org/livestream/
7•altilunium•1h ago•0 comments

Code Execution Through Email: How I Used Claude to Hack Itself

https://www.pynt.io/blog/llm-security-blogs/code-execution-through-email-how-i-used-claude-mcp-to-hack-itself
46•nonvibecoding•4h ago•22 comments

I want an iPhone Mini-sized Android phone (2022)

https://smallandroidphone.com/
275•asimops•13h ago•384 comments

Original Xbox Hacks: The A20 CPU Gate (2021)

https://connortumbleson.com/2021/07/19/the-xbox-and-a20-line/
62•mattweinberg•7h ago•11 comments

Altermagnets: The first new type of magnet in nearly a century

https://www.newscientist.com/article/2487013-weve-discovered-a-new-kind-of-magnetism-what-can-we-do-with-it/
357•Brajeshwar•19h ago•91 comments

I was wrong about robots.txt

https://evgeniipendragon.com/posts/i-was-wrong-about-robots-txt/
101•EPendragon•10h ago•88 comments

New battery has life so long you may never have to recharge

https://www.neowin.net/news/this-amazing-new-battery-has-life-so-long-you-may-never-have-to-recharge/
14•Bluestein•37m ago•7 comments

Metaflow: Build, Manage and Deploy AI/ML Systems

https://github.com/Netflix/metaflow
46•plokker•14h ago•4 comments

Inside the box: Everything I did with an Arduino starter kit

https://lopespm.com/hardware/2025/07/15/arduino.html
87•lopespm•2d ago•8 comments

A Tale of Two Red-Bearded Visionaries

https://nemanjatrifunovic.substack.com/p/a-tale-of-two-red-bearded-visionaries
4•whobre•2d ago•1 comments

Show HN: A 'Choose Your Own Adventure' written in Emacs Org Mode

https://tendollaradventure.com/sample/
124•dskhatri•12h ago•17 comments

Mistakes Microsoft made in the Xbox security system (2005)

https://xboxdevwiki.net/17_Mistakes_Microsoft_Made_in_the_Xbox_Security_System
67•davikr•10h ago•29 comments

Pgactive: Postgres active-active replication extension

https://github.com/aws/pgactive
307•ForHackernews•1d ago•78 comments

Intel's retreat is unlike anything it's done before in Oregon

https://www.oregonlive.com/silicon-forest/2025/07/intels-retreat-is-unlike-anything-its-done-before-in-oregon.html
168•cbzbc•15h ago•255 comments

A 1960s schools experiment that created a new alphabet

https://www.theguardian.com/education/2025/jul/06/1960s-schools-experiment-created-new-alphabet-thousands-children-unable-to-spell
56•Hooke•1d ago•56 comments

NINA: Rebuilding the original AIM, AOL Desktop, Yahoo and ICQ platforms

https://nina.chat/
13•ecliptik•3h ago•2 comments

Artisanal handcrafted Git repositories

https://drew.silcock.dev/blog/artisanal-git/
174•drewsberry•14h ago•44 comments

A bionic knee integrated into tissue can restore natural movement

https://news.mit.edu/2025/bionic-knee-integrated-into-tissue-can-restore-natural-movement-0710
37•gmays•2d ago•1 comments

Show HN: Improving search ranking with chess Elo scores

https://www.zeroentropy.dev/blog/improving-rag-with-elo-scores
158•ghita_•20h ago•52 comments

Open, free, and ignored: the afterlife of Symbian

https://www.theregister.com/2025/07/17/symbian_forgotten_foss_phone_os/
27•mdp2021•2h ago•7 comments

How and where will agents ship software?

https://www.instantdb.com/essays/agents
134•stopachka•16h ago•61 comments

A Rust shaped hole

https://mnvr.in/rust
100•vishnumohandas•1d ago•229 comments

Task Runner Census 2025

https://aleyan.com/blog/2025-task-runners-census/
14•aleyan•2d ago•4 comments

Scanned piano rolls database

http://www.pianorollmusic.org/rolldatabase.php
60•bookofjoe•4d ago•14 comments

Roman dodecahedron: 12-sided object has baffled archaeologists for centuries

https://www.livescience.com/archaeology/romans/roman-dodecahedron-a-mysterious-12-sided-object-that-has-baffled-archaeologists-for-centuries
68•bookofjoe•2d ago•118 comments

Blue Pencil no. 18–Some history about Arial

https://www.paulshawletterdesign.com/2011/09/blue-pencil-no-18%e2%80%94some-history-about-arial/
37•Bluestein•3d ago•10 comments
Open in hackernews

A Rust shaped hole

https://mnvr.in/rust
100•vishnumohandas•1d ago

Comments

blashyrk•1d ago
Someone really needs to show Nim to the author :). It checks all of their boxes and then some
Symmetry•15h ago
I was thinking that too. There are many cases where you do want to manage memory yourself, and in that case you should likely use Rust or maybe Zig if you can choose your own tool. But if you don't want to manage your own memory Nim works nicely, though IMO it requires adherence to a style guide more than most languages.
timeon•3h ago
Depends what you do but most of the time you do not need to do anything special about memory management in Rust. That is why people try to use it for other things then just system programming.
elcritch•15h ago
Yep it’s ideal for this sort of application without the headache of Rust. Plus it’s helpful it can compile to C,C++, or JavaScript. So take your pick.
turboponyy•1d ago
> While I can jump through hoops to compile JavaScript into a binary, such wouldn't feel "solid". And the very point of writing a native program in the first place is to make it feel solid

You can use Bun to compile to native binaries without jumping through hoops. It's not mature, but it works well enough that we use it at work.

genshii•16h ago
It's definitely nice for certain use cases. I just wish the binaries weren't so huge (~60MB + your actual source code).
j-krieger•16h ago
I write Gleam for this. A rust like language on the erlang VM. It's neat, but not widely used.
giancarlostoro•16h ago
I have been wanting to use Gleam more, but I havent found the right project or time. I can prototype drastically easier using Python.
DarkNova6•16h ago
The table in the end sums it up nicely.

Rust allows low level programming and static compilation, while still providing abstraction and safety. A good ecosystem and stable build tools help massively as well.

It is one of the few languages which managed to address a real life need in novel ways, rather than incrementing on existing solutions and introducing new trade offs.

tux3•16h ago
>To paraphrase Norvig's Latency numbers a programmer should know, if we imagine a computer that executes 1 CPU instruction every second, it would take it days to read from RAM.

It's a detail, but this is a little bit off. RAM latency is roughly around ~100ns, CPUs average a couple instructions per cycle and a few cycles per ns.

Then in the analogy, a stall on RAM is about a 10 minute wait; not quite as bad as losing entire days.

jlokier•14h ago
In current machines, that's way off depending on how you choose to count "1 CPU instruction" for the metaphor.

Take Apple's latest laptops. They have 16 CPU cores, 12 of those clocking at 4.5 GHz and able to decode/dispath up to 10 instructions per cycle. 4 of those clocking at 2.6 GHz, I'm not sure about their decode/dispatch width but let's assume 10. Those decoder widths don't translate to that many instructions-per-cycle in practice, but let's roll with it because the order of magnitude is close enough.

If the instructions are just right, that's 824 instructions per nanosecond. Or, roughly a million times faster than the 6502 in the Apple-II! Computers really have got faster, and we haven't even counted all the cores yet.

Scaling those to one per second, a RAM fetch taking 100ns would scale to 82400 seconds, which 22.8 hours, just short of a day.

Fine, but we forgot about the 40 GPU cores and the 16 ANE cores! More instructions per ns!

Now we're definitely into "days".

For the purpose of the metaphor, perhaps we should also count the multiple lanes of each vector instruction on the CPU, and lanes on the GPU cores, as if thery were separate processing instructions.

One way to measure that, which seems fair and useful to me, is to look at TOPS instead - tera operations per second. How many floating-point calculations can the processor complex do per second? I wasn't able to find good figures for the Apple M4 Max as a whole, only the ANE component, for which 38 TOPS is claimed. For various reasons tt's reasonable to estimate the GPU is the same order of magnitude in TOPS on those chips.

If you count 38 TOPS as equivalent to "CPU instructions" in the metaphor, then scale those to 1 per second, a RAM fetch taking 100ns scales to a whopping 43.9 days on a current laptop!

tux3•12h ago
If you're counting all instruction executing in parallel with the maximum on-paper IPC on all CPUs, accelerators, and GPUs, the number your get has no clear relation to RAM latency. It really is comparing apples and oranges.

This scenario where all your 16 cores are doing 10 instructions per clock assumes everything is running without waiting, at full instruction-level and CPU-level parallelism. It's a measure of the maximum paper throughput when you're not blocked waiting on memory.

You could compare that to the maximum throughput of the RAM and the memory subsystem, and that would give you meaningful numbers (for instance, how many bytes/cycle can my cores handle? How many GB/s can my whole system process?).

Trying to add up the combined throughput of everything you can on one side and the latency of a single fetch on the other side will give you a really big number, but as a metaphor it will be more confusing than anything.

renewiltord•10h ago
This seems like the classic 9 women making a baby in 1 month. Even if the CPU can execute 824 instructions per nanosecond, it can't execute 1 instruction in 1/824 nanoseconds. You can't mix throughput and latency like that.
genshii•16h ago
This hits close to home. TypeScript is also my language of choice for 90% of the software I write. I agree with the author that TypeScript is very close to the perfect level of abstraction, and I haven't seen another language with a type system that's nearly as enjoyable to use. Of course, TS (any by extension JS) obviously has its issues/complications. Bun solves a lot of the runtime-related issues/annoyances though.

For the other 10% software that is performance-sensitive or where I need to ship some binary, I haven't found a language that I'm "happy" with. Just like the author talks about, I basically bounce between Go and Rust depending on what it is. Go is too simple almost to a fault (give me type unions please). Rust is too expressive; I find myself debugging my knowledge of Rust rather than the program (also I think metaprogramming/macros are a mistake).

I think there's space in the programming language world for a slightly higher level Go-like language with more expressiveness.

ashishb•15h ago
TypeScript is good as a language. You can't generate static binaries out of it (except Docker images) and that itself is a deal breaker.
genshii•15h ago
Yeah, that's definitely a huge drawback. Bun lets you get pretty close though with the `--compile` flag: https://bun.sh/docs/bundler

Too bad the binaries are 60MB at a minimum :(

Tade0•15h ago
I mean you can, they're just inappropriately large.
wk_end•15h ago
I'd love to see someone develop a compiler for TypeScript that got, say, Ocaml-like performance. There's a bunch of reasons why that'd be tough though - you'd probably want a language very-similar-to-but-not-quite-like-TypeScript.
ellg•15h ago
its called C#
wk_end•15h ago
C# is a lovely language but it's not that similar to TypeScript. The big distinction (for me) is that it's nominally-typed and much more rigid. Unless things have changed a lot since I last touched it (admittedly a while ago):

You can't synthesize ad hoc union types (https://www.typescriptlang.org/docs/handbook/2/everyday-type...)

There's no notion of literal types (https://www.typescriptlang.org/docs/handbook/2/everyday-type...)

There's no type narrowing (which gets you a kind of sum type) (https://www.typescriptlang.org/docs/handbook/2/narrowing.htm...)

Most of the type maniuplation features (keyof, indexed access types, conditional types, template literal types...) are missing (https://www.typescriptlang.org/docs/handbook/2/types-from-ty...)

pragmatic•12h ago
Close but not quite.
williamstein•15h ago
This is probably the closest thing to that: https://www.assemblyscript.org/
wk_end•15h ago
The documentation is really incomplete. It's not at all clear how similar to TypeScript this is...does this support structural subtyping? Type manipulation? Iterators/generators? Async?
skybrian•5h ago
You can’t? I haven’t used it, but what’s wrong with “deno compile?”

https://docs.deno.com/runtime/reference/cli/compile/

shim__•1h ago
Sounds like electron but for cli
daxfohl•15h ago
I'm surprised ocaml doesn't have more market share here. Native, fast, robust type system, GC, less special syntax than rust, less obtuse than Haskell.
pragmatic•12h ago
No libraries.

All the niche languages have a chicken and egg problem.

Only way around that is to be able to piggy back on C or JavaScript or Java.

daxfohl•11h ago
Yeah, though when I say that I mean more like I'm surprised the ecosystem itself hasn't matured more. Rust and Go have both built solid ecosystems up from scratch, but it's a shame that OCaml hasn't since it's a nice middle ground between the two.
andrewflnr•10h ago
I really considered one of the BuckleScript/js_of_ocaml languages for my current frontend project, but went with Typescript for basically conservatism/conventionalism reasons. I was already taking some arguably unnecessary technical risks on that project and wasn't sure I could afford more. I agree that I really wish OCaml or something close to it was mainstream.
lostmsu•6h ago
Until recently it did not have multithreading
renewiltord•10h ago
I recently came to a production Typescript codebase and it took minutes to compile. Strangely, it could not behave correctly without a linter rule `no-floating-promises` but the linter also took minutes to lint the codebase. It was an astounding exercise in patience. Faster linters like oxlint exist but they don't have a notion of cross-file types so `no-floating-promises` is impossible on them.

The worst part is that `no-floating-promises` is strange. Without it, Knex (some ORM toolkit in this codebase) can crash (segfault equivalent) the entire runtime on a codebase that compiles. With it, Knex's query builders will fail the lint.

It was confusing. The type system was sophisticated enough that I could generate a CamelCaseToSnakeCase<T> type but somehow too weak to ensure object borrow semantics. Programmers on the codebase would frequently forget to use `await` on something causing a later hidden crash until I added the `no-floating-promises` lint, at which point they had to suppress it on all their query builders.

One could argue that they should just have been writing SQL queries and I did, but it didn't take. So the entire experience was fairly nightmarish.

Sophistifunk•7h ago
I very much enjoy reading and writing TS code. What I don't enjoy is the npm ecosystem (and accompanying mindset), and what I can't stand is trying to configure the damn thing. I've been doing this since TSC was first released, and just the other day I wasted hours trying to make a simple ts-node command line program work with file-extension-free imports and no weird disagreements between the ts-node runner and the language server used by the editor.

And then gave up in disgust.

Look, I'm no genius, not by a long shot. But I am both competent and experienced. If I can't make these things work just by messing with it and googling around, it's too damned hard.

childintime•1h ago
Fully agree. Try bun.
tptacek•16h ago
I don't think you need an elaborate process of elimination when one of your axioms is "must manage memory manually".
yccs27•15h ago
> Memory management was indeed the sore sticking point, why Rust hadn't appealed to me earlier.

The author doesn't want manual memory management, but still decides to go with Rust.

tptacek•15h ago
Their rubric is literally just 3 items: "native compilation", "abstractions", and "manual memory management". Had they put that little table at the front of the article, there wouldn't even need to be an article: the table basically says "I'm going to use Rust". That's fine!
JoelMcCracken•14h ago
The author really doesn't want to do manual memory management. The table is there to summarize things discussed, but he never says he wants to do manual memory management. I just went back and checked. If you do find something that indicates that, I'd appreciate you pointing it out to me, because idgi
tptacek•14h ago
I read the article twice, but I could also just be wrong; it's not that big a deal.
Expurple•13h ago
No problem, get some sleep in that case :D
ignoramous•10h ago
> The table is there to summarize things discussed, but he never says he wants to do manual memory management.

  But it requires me to manage memory and lifetimes, which I think is something the compiler should do for me.
The author wants the compiler to do memory management? How does Rust achieve this?
steveklabnik•10h ago
The compiler works with you to ensure that you’re not misusing memory. If you make a mistake, it will let you know.

You’re not often manually managing memory in the same sense as other low-level languages. You’re not invoking malloc and free directly. Thanks to ownership, when you do allocate, Rust will call free for you.

It’s somewhere in between fully manual and fully automatic. It can feel more like one or the other based on what you’re doing, but most of the time, in average, it feels like automatic.

adastra22•5h ago
It is better to think of Rust having explicit memory management, rather than manual memory management. C/C++ has manual memory management: the burden is on you to do it correctly. If you fuck up, your program will have bugs. Rust requires that your code be explicit about memory issues, but the compiler works with you to achieve that. if your code compiles it is correct; if it doesn't compile, the error points out what needs to be fixed. When I write Rust it rarely feels like I am taking on that burden myself.
Expurple•14h ago
I don't think you need an elaborate comment when one of your axioms is "must not read the post that you're responding to".
eviks•4h ago
He's saying exactly the opposite

> Rust... But it requires me to manage memory and lifetimes, which I think is something the compiler should do for me.

ashishb•16h ago
I actively seek out tools written in static languages. They are less fragile and have a longer shelf life.

https://ashishb.net/programming/maintaining-android-app/

Expurple•14h ago
I agree so hard. That's why I use Hugo for my website. Speed was always only a bonus
slowcache•15h ago
Odin has been really growing on me lately as a language that checks all of those boxes. String types, first class allocators, built in tests, a batteries included philosophy, and ease of use are some of the things that really drew me towards it.

I really wanted to like rust and I wrote a few different small toy projects in it. At some point knowledge of the language becomes a blocker rather than knowledge the problem space, but this is a skill issue that I'm sure would lessen the more I used it.

What really set me off was how every project turned into a grocery list of crates that you need to pull in in order to do anything. It started to feel embarrassing to say that I was doing systems programming when any topic I would google in rust would lead me to a stack overflow saying to install a crate and use that. There seemed to be an anti-DIY approach in the community that finally drew me away.

klntsky•15h ago
What's the difference between anti-DIY and "batteries included"?
tialaramex•2h ago
If Ginger Bill thinks some niche feature might be useful then baking it into Odin is "batteries included" if not, having it would be anti-DIY. This is very much Bill's language. If what you're looking for is that auteur stamp you won't find it in C or Rust or Typescript but you will find it in languages like Jai, Odin, Hare, maybe Zig.

If that creator's vibe happens to match yours this could be beautiful, at least for personal projects. It's hard to imagine this scaling. A triple A studio hiring panel: "You've applied for a job but we write only Jai here. We notice you haven't submitted any obsessive fan art about Jonathan Blow. Maybe talk us through the moment you realised he was right about everything?"

Expurple•15h ago
re:crates https://web.archive.org/web/20250420085150/https://wiki.alop...
deathanatos•3h ago
> String types

It's a byte string.

> rune is the set of all Unicode code points.

We copied the awful name from Go … and the docs are wrong.

Five different boolean types?

Zero values. (Every value has some default value, like in Go.)

Odin also includes the Billion Dollar Mistake.

> There seemed to be an anti-DIY approach in the community that finally drew me away.

It's a "let a thousand flowers bloom" approach, at least until the community knows which design stands a good chance of not being a regretted addition to the standard library.

bee_rider•15h ago
I’m not sure what his abstraction column really means, nuts and bolts-wise. But, Fortran is native, you get to allocate your own memory, and it has object oriented features (maybe that’s abstraction).
tines•15h ago
Very cool, I wish the author good luck! I've been writing a compiler in Rust for a few months now and I absolutely love it. The ways it solves most of the problems it addresses feel like the "right" way to do things.

There are some things that feel a little weird, like the fact that often when you want a more complex data structure you end up putting everything in a flat array/map and using indices as pointers. But I think I've gotten used to them, and I've come up with a few tricks to make it better (like creating a separate integer type for each "pointer" type I use, so that I can't accidentally index an object array with the wrong kind of index).

Rust is one of those languages that change how you think, like Haskell or Lisp or Forth. It won't be easy, but it's worth it.

lenkite•6h ago
The best way to use Rust is to circumvent use of the borrow-checker and lifetimes and use indices everywhere! Suddenly, it becomes more pleasant and easy to refactor :).
uecker•15h ago
It is a bit unclear to me why somebody who rejects C++ because "I once spent an entire year in the heaven of C++, walking around in a glorious daze of std::vector and RAII, before one day snapping out of it and realizing that I was just spawning complexity that is unrelated to the problem at hand." (which I can absolutely agree with!) is picking Rust from all options. If there is a language that can rival C++ in terms of complexity, it is Rust.
dijit•15h ago
You’re right that Rust is a ball of complication.

I am a fan of Rust but it’s definitely a terse language.

However there are definitely signs that they have thought about making it as readable as possible (by omitting implicit things unless they’re overwritten, like lifetimes).

I’m reminded also about a passage in a programming book I once read about “the right level of abstraction”. The best level of abstraction is the one that cuts to the meat of your problem the quickest - spending a significant amount of time rebuilding the same abstractions over and over (which, is unfortunately often the case in C/C++) is not actually more simple, even if the language specifications themselves are simpler.

C codebases in particular, to me, are nearly inscrutable unless I spend a good amount of time unpicking the layers of abstractions that people need to write to make something functional.

I still agree that Rust is a complex language, but I think that largely just means it’s frontloading. a lot of the understanding about certain abstractions.

uecker•15h ago
I do not really agree with respect to C. I often have to deal with C code written by unexperienced programmers. It is always relatively easy to refactor it step by step. For C++ this is much more painful because all the tools invented to make the code look concise make it extremely hard to follow and change. From the feature set, I would say that Rust is the same (but I have no experience refactoring Rust code).
AstralStorm•14h ago
In personal experience, the much stronger and composite type model in Rust makes it easier to refactor.

Adding features in particular is a breeze and automatically the compiler/language will track for you the places that use only old set of traits.

Tooling is still newer though and needs polish. Generic handling is interesting at times and there are related missing features for that in the language, vis a vis specializations in particular.

Basic concurrency handling is also quite different in Rust than other languages, but thus usually safer.

uecker•14h ago
I am wondering about this. In C the nice thing is that you usually change things locally. A line of code does not depend on a million other things. I can't quite see how this works in Rust... At least in C++, template, overloading, etc. can make a single line depend on a lot of things.
Expurple•13h ago
> A line of code does not depend on a million other things.

But it does! To qoute my top-level comment:

> What about about race conditions, null pointers indirectly propagated into functions that don't expect null, aliased pointers indirectly propagated into `restrict` functions, and the other non-local UB causes?

In other words: you set some pointer to NULL, this is OK in that part of your program, but then the value travels across layers, you've skipped a NULL check somewhere in one of those layers, NULL crosses that boundary and causes UB in a function that doesn't expect NULL. And then that UB itself also manifests in weird non-local effects!

Rust fixes this by making nullability (and many other things, such as thread-safety) an explicit type property that's visible and force-checked on every layer.

Although, I agree that things like macros and trait resolution ("overloading") can be sometimes hard to reason about. But this is offset by the fact that they are still deterministic and knowable (albeit complex)

uecker•13h ago
This is true to some degree, but not really that much in practice. When refactoring you just add assertions for NULL (and the effect of derefencing a NULL in practice is a trap - that it UB in the spec is completely irrelevant. in fact it helps because it allows compilers to turn it a trap without requiring it on weak platforms). Restrict is certainly dangerous, but also rarely used and a clear warning sign, compare it to "unsafe". The practical issues in C are bounds checking and use-after-free. Bounds checking I usually refactor into safe code quickly. Use-after-free are the one area where Rust has a clear advantage.
Expurple•13h ago
I agree that in practice NULL checking is one of the easier problems. I used it because it's the most obvious and easy to understand. I can't claim which kinds of unsoundness in C code are more common and problematic in practice. But that's not even interesting, given that safe Rust (and other safe languages) solve every kind of unsoundness.

> in fact it helps because it allows compilers to turn it a trap without requiring it on weak platforms

The "shared xor mutable" rule in Rust also helps the compiler a lot. It basically allows it to automatically insert `restrict` everywhere. The resulting IR is easier to auto-vectorize and you don't need to micro-optimize so often (although, sometimes you do when it comes to eliminating bound checks or stack copies)

> Restrict is certainly dangerous, but also rarely used and a clear warning sign, compare it to "unsafe".

It's NOT a clear warning sign, compared to `unsafe`. To call an unsafe function, the caller needs to explicitly enter an `unsafe` block. But calling a `restrict` function looks just like any normal function call. It's easy to miss an a code review or when upgrading the library that provides the function. That the problem with C and C++, really. The `unsafe` distinction is too useful to omit.

uecker•13h ago
You are not wrong, but also not really right. In practice, I never had a problem with "restrict". And this is my point about Rust being overengineered. While it solves real problems, you need to exaggerate the practical problems in C to justify its complexity.
Expurple•12h ago
> In practice, I never had a problem with "restrict".

That's exactly because it's too dangerous and the developers quickly learn to avoid it instead of using it where appropriate! Same with multithreading. C leaves a lot of optimization on the table by making the available tools too dangerous and forcing people to avoid them altogether.

That's how you get stuff like memory-safe Rust PNG decoders being 1.5x faster than established C alternatives that had much more effort put into them (https://www.reddit.com/r/rust/comments/1ha7uyi/memorysafe_pn...). Or the first parallel CSS engine being written in Rust after numerous failed attempts in C++ (https://www.reddit.com/r/rust/comments/7dczj9/can_stylo_be_i...). Read those threads in full, there are some good explanations there.

> you need to exaggerate the practical problems in C

I thought, the famous "70% of vulnerabilities" report settled this once and for all.

uecker•4h ago
Na, sorry. The "70%" is just nonsense. And cherry picking individual benchmarks too.
Expurple•4h ago
> The "70%" is just nonsense.

Care to elaborate why?

> And cherry picking individual benchmarks too.

Do you have any general, comprehensive benchmarks or statistics that would indicate the opposite? I would include one if I had one at hand, because that would be a stronger argument! But I'm not aware of such benchmarks. I have to cherry pick individual projects. I don't want to.

I still claim that, as a general trend, Rust replacements are faster while also being less bug-prone and taking much less time to write. Another such example is ripgrep.

antonvs•4h ago
You're focusing purely on the problem-fixing aspects, but Rust's expressiveness is why I like it.

C can't match that. In C, you're basically acting as a human compiler, writing lots of code that could be generated if you used a more expressive language. Plus, as has been mentioned, it supports refactoring easily and safely better than any language outside of the Haskell/ML space.

The advantages of Rust are a package which includes safety, expressiveness, refactoring support. You don't need to exaggerate anything for that package to make sense.

uecker•4h ago
I am not criticizing anyone for preferring Rust. I reject the idea that its complexity needs to imposed on everybody because of "safety"
antonvs•2h ago
The "impose on everybody" is based on clear, objective metrics at the national and international level.

The fact that you, as an individual, prefer to use an unsafe, weakly typed language isn't very relevant to that.

The issue is not that it's not possible to write secure programs in C, the issue is that in practice, on average, people don't.

Pushing the use of memory-safe languages will reduce the number of security vulnerabilities in the entire software ecosystem.

nemothekid•10h ago
>When refactoring you just add assertions for NULL

This is a line of thinking I used to see commonly when dynamic typing was all the rage. I think the difference comes from people who view primarily work on projects where they are the sole engineer vs ones where they work n+1 other engineers.

"just add assertions" only works if you can also sit on the shoulder of everyone else who is touching the code, otherwise all it takes is for someone to come back from vacation, missing the refactor, to push some code that causes a NULL pointer dereference in an esoteric branch in a month. I'd rather the compiler just catch it.

Furthermore, expressive type systems are about communcation. The contracts between functions. Your CPU doesn't case about types - types are for humans. IMO you have simply moved the complexity from the language into my brain.

uecker•4h ago
This was about refactoring a code base where a type is assumed to be non-null but it is not obvious. You can express also in C on interfaces that a pointer is non-null.
staunton•3h ago
> interfaces

You mean obsolete and subtly wrong comments buried among preprocessor directives in some far-upstream header files?

anon-3988•4h ago
> This is true to some degree, but not really that much in practice. When refactoring you just add assertions for NULL (and the effect of derefencing a NULL in practice is a trap - that it UB in the spec is completely irrelevant.

This happens a lot in discussion about programming complexity. What you are doing is changing the original problem to a much simpler one.

Consider a parsing function parse(string) -> Option<Object>

This is the original problem, "Write a parsing function that may or may not return Object"

What a lot of people do is they sidetrack this problem and solve a much "simpler problem". They instead write parse(string) -> Object

Which "appears" to be simpler but when you probe further, they handwave the "Option" part to just, "well it just crashes and die".

This is the same problem with exceptions, a function "appears" to be simple: parse(string) -> Object but you don't see the myriads of exceptions that will get thrown by the function.

uecker•4h ago
I guess it depends on what the problem is. If the problem is being productive and being able to program without pain "changing the original problem to a much simpler one" is a very good thing. And "crash and die" can be a completely acceptable way to deal with it. Rust's "let it panic" is not at all different in this respect.

But in the end, you can write Option just fine it C. I agree though that C sometimes can not express things perfectly in the type system. But I do not agree that this is crucial for solving these problems. And then, also Rust can not express everything in the type system. (And finally, there are things C can express but Rust can't).

Expurple•3h ago
> in the end, you can write Option just fine it C.

No, you can't. In the sense that the compiler doesn't have exhaustiveness checks and can't stop you from accessing the wrong variant of a union. An Option in C would be the same as manually written documentation that doesn't guarantee anything.

std::optional in C++ is the same too. Used operator* or operator-> on a null value? Too bad, instant UB for you. It's laughably bad, given that C++ has tools to express tagged unions in a more reliable way.

> And then, also Rust can not express everything in the type system. (And finally, there are things C can express but Rust can't).

That's true, but nobody claims otherwise. It's just that, in practice, checked tagged unions are a single simple feature that allows you to express most things that you care about. There's no excuse for not having those in a modern language.

And part of the problem is that tagged unions are very hard to retrofit into legacy languages that have null, exceptions, uninitialized memory, and so on. And wouldn't provide the full benefit even if they could be retrofitted without changing these things.

anon-3988•3h ago
Yes, all I am saying is that we have to be honest what level of problems we are solving when we encounter a complicated solution.

The solution have to scale linearly with the problem at hand, that is what it means to have a good solution.

I agree with the article that Rust is overkill for most use cases. For most projects, just use a GC and be done with it.

> But I do not agree that this is crucial for solving these problems. And then, also Rust can not express everything in the type system.

This can be taken as a feature. For example, is there a good reason this is representable?

struct S s = 10;

I LOVE the fact that Rust does not let me get away with half-ass things. Of course, this is just a preference. Half of my coding time is writing one-off Python scripts for analysis and data processing, I would not want to write those in Rust.

> But in the end, you can write Option just fine it C.

Even this question have a deeper question underneath it. What do you mean by "just fine"? Because to me, tagged enums or NULL is NOT the same thing as algebraic data types.

This is like saying floating points are just fine for me for integer calculations. Maybe, maybe for you its fine to use floating points to calculate pointers, but for others it is not.

rstuart4133•12h ago
> I can't quite see how this works in Rust...

You won't understand it unless refactor some Rust programs.

Bunny summed it up rather well. He said in most languages, when pull on some thread, you end disappearing into a knot and you're changes are just creating a bigger knot. In Rust, when pull on a thread, the language tells you where it leads. Creating a bigger knot generally leads to compile errors.

Actually he didn't say that, but I can't find the quote. I hope it was something like that. Nonetheless he was 100% spot on. That complexity you bemoan about the language is certainly there - but it's different to what you have experienced before.

In most languages, complex features tend lead to complex code. That's what made me give up on Python in the end. When you start learning Python, it seems a delightfully simple yet powerful language. But then you discover metaclasses, monkey patching, and decorators, which all seem like powerful and useful tools, and you use them to do cool things. I twisted Python's syntax into grammar productions, so you could write normal looking python code that got turned into an LR(1) parser for example. Then you discover other peoples code that uses those features to produce some other cute syntax, and it has a bug, and when you look closely your brain explodes.

As you say C doesn't have that problem, because it's such a simple language. C++ does have that problem, because it's a very complex language. I'm guessing you are making deduction from those two examples that complex languages lead to hard to understand code. But Rust is the counter example. Rust's complexity is forces you to write simple code. Turns out it's the complexity of the code that matters, not the complexity of the language.

uecker•4h ago
I only have limited experience with Rust (only playing around a bit). But it seems the language forces you to structure the code in a specific way (and you seem to agree). This is good, because it prevents you from making a mess (at some level at least). But what others report (and it matches my limited experience) is that it makes the structure of the code very rigid. So I do not quite see how this does not limit refactoring? What some of you describe in this thread is type-directed refactoring (i.e. you change a type and the compiler tells what you need to change), but is this not limited to relatively basic changes?

In C, you can make partial changes and accept a temporary inconsistency. This gives you a lot of flexibility that I find helpful.

Expurple•3h ago
I'll put it like this. Rust causes you to refactor more often and do a full refactoring at once (because the interfaces are so rigid), but it makes it easy to do a full (and correct) refactoring very quickly. Think of it as docs being part of the interface and the compiler forcing you to always update the docs. That's an amazing property
pjmlp•2h ago
Preprocessor enters the scene.

Then we have the functions that might be re-entrant or not, in the presence of signals, threads,...

bryanlarsen•10h ago
> but I have no experience refactoring Rust code

But you're willing to write many comments complaining that Rust is hard to refactor. Rust is the easiest language to refactor with I've ever worked in, and I've used a couple dozen or so. When you want to change something, you change it, and then fix compiler errors until it stops complaining. Then you run it, and it works the first time you run it. It's an incredible experience to worry so little about unknown side-effects.

Dylan16807•9h ago
> But you're willing to write many comments complaining that Rust is hard to refactor.

Their refactoring comments look focused on C versus C++ to me, with a bit of guessing Rust is like C++ in a way that is clearly labeled as speculation.

So I don't see the problem with anything they said about refactoring.

bsder•9h ago
> Rust is the easiest language to refactor with I've ever worked in

Oh? So how do you refactor a closure into a named function in Rust?

I have found this to be of the most common failure modes that makes people want to punch the monitor.

(Context: in almost all programming languages, a closure is practically equivalent to an unnamed function--refactoring a closure to a named function tends to be pretty straightforward. This isn't true for Rust--closures pick up variable lifetime information that can be excruciatingly difficult to unwind to a named function.)

bryanlarsen•8h ago
Set the type of all the parameters to your new function to bool, then compile. The compiler error will tell you, "Error: you passed a foo<'bar, baz> instead of a bool". Then you change the type in the function's parameter to "foo<'bar, baz>".
afdbcreid•5h ago
You invoke the assist of rust-analyzer that does that automatically.
adastra22•5h ago
Also, although it was not designed with this in mind, the described process adopts VERY well to LLMs. You can make a refactoring change, then tell the LLM to "run cargo check and fix the errors." And it does a very good job of doing this.
uecker•4h ago
No, I wrote that Rust is too complex. And I responded to a comment that claims that C is hard to refactor, and this does not match my experience.
anon-3988•5h ago
> I do not really agree with respect to C. I often have to deal with C code written by unexperienced programmers. It is always relatively easy to refactor it step by step.

Really? How confident are you to change a data structure that uses an array with linear search lookup to a dictionary? Or a pointer that now is nullable (or is now never null)?

Unless you have rigorous test or the code is something trivial, this would be a project of its own.

I am pretty sure I can swap out the implementation of the dictionary in the rust compiler and by the time the compilation issues are worked out, the code would be correct by the end of it (even before running the tests)

sigi64•1h ago
I can compare programming and refactoring large code bases in C and C++, Rust, and Python, from system and parsing and protocol libraries to asynchronous multi-threaded servers in the mentioned languages.

Refactoring Rust projects is clearly the easiest because the compiler and type system ensure the program is correct at least in terms of memory access and shared resource access. It doesn't protect me from memory leaks and logical errors. But since Rust has a built-in testing framework, it's quite easy to prepare tests for logical errors before refactoring.

C/C++ refactoring is a nightmare - especially in older projects without modern smart pointers. Every change in ownership or object lifetime is a potential disaster. In multi-threaded applications it's even worse - race conditions and use-after-free bugs only manifest at runtime, often only in production. You have to rely on external tools like Valgrind or AddressSanitizer.

Python has the opposite problem - too much flexibility. You can refactor an entire class, run tests, everything passes, but then in production you discover that some code was dynamically accessing an attribute you renamed. Type hints help, but they're not enforced at runtime.

Rust forces you to solve all these problems at compile time. When you change a lifetime or ownership, the compiler tells you exactly where you need to fix it. This is especially noticeable in async code - in C++ you can easily create a dangling reference to a stack variable that an async function uses. In Rust, it simply won't compile.

The only thing where Rust lags a bit is compilation speed during large refactors. But that's a small price to pay for the certainty that your code is memory-safe.

Another area where Rust absolutely excels is when using AI agents like Claude Code. It seems to me that LLMs can work excellently with Rust programs, and thanks to the support of the type system and compiler, you can get to functional code quickly. For example, Claude Code can analyze Rust programs very well and generate documentation and tests.

I think Rust with an AI agent has the following advantages:

Explicit contract - the type system enforces clear function interfaces. The AI agent knows exactly what a function expects and what it returns.

Compiler as collaborator - when AI generates code with an error, it gets a specific error message with the exact location and often a suggested solution. This creates an efficient feedback loop.

Ownership is explicit - AI doesn't have to guess who owns data and how long it lives. In C++ you often need to know project conventions ("here we return a raw pointer, but the caller must not deallocate it").

Fewer implicit assumptions - in Python, AI can generate code that works for specific input but fails on another type. Rust catches these cases at compile time.

jplusequalt•15h ago
>If there is a language that can rival C++ in terms of complexity

Fair, but this relative. C++ has 50 years of baggage it needs to support--and IMO the real complexity of C++ isn't the language, it's the ecosystem around it.

tines•15h ago
The two are incomparable in both quality and quantity. The complexity of Rust comes from the fact that it's solving complex problems. The complexity of C++ comes from a poorly thought out design and backwards-compatibility. (Not to slight the standards committee; they are smart people, and did the best with what they had.)

Anothere way of putting it is, if you didn't care about backwards-compatibility, you could greatly simplify C++ without losing anything. You can't say the same about Rust; the complexity of Rust is high-entropy, C++'s is low-entropy.

uecker•15h ago
I would say that most of the complexity in both cases comes from overengineering.
tines•15h ago
Can you give some examples of Rust and C++ design that are over engineered?
uecker•14h ago
For C++, just take lambda captures, you can do [&], [=], [a], [&a], [a = b] (and I probably forgot half), the many way you can do initialization in C++ became a meme, but it really permeates the whole language whose design is driven by enthusiasts and people who have an interest to make it more complex (trainers, book authors, consultants, etc.)

For Rust, I think it is a bit of a different story and it is harder to point to specific features. The language is clearly much better designed (because it was more designed and did not evolve so much) and because of its roots in functional programming. Just overall, the complexity is too high in my opinion and it a bit too idealistic and not pragmatic enough.

LoganDark•7h ago
> it a bit too idealistic and not pragmatic enough

This is an ideal programming language for certain types of people. It also gives the programming language certain properties that make it useful when provable correctness is a concern (see Ferrocene).

AlotOfReading•6h ago
Last time I talked to the ferrocene people they had no plans to do anything with formal methods. Has their scope expanded?
_flux•58m ago
Maybe it was intended to refer to RustBelt.

I haven't been following their work, though. It seems they are working on stacked borrows.

bfrog•7h ago
The language is highly productive, it’s pragmatic enough. There’s no perfect language until our brains can directly describe what we want a machine to do without intermediary translation layers like C.
saagarjha•2h ago
I think captures are mostly reasonable and fine (and other languages have similar constructs). Initialization is completely broken, yes.
anon-3988•5h ago
For C++ specifically, constructors. Just have functions for gods sake.
materielle•7h ago
The C++ standard committee is definitely smart. But language design requires sense beyond just being smart.

They didn’t do the best with what they had. Sure, some problems were caused by C backwards compatibility.

But so much of the complexity and silliness of the language was invented by the committee themselves.

pjmlp•2h ago
As someone that really enjoys C++, I would say that the current issues are cause by lack of preview implementations before being voted into the standard, this is just broken, but there are not enough people around to be able to turn the ship around.

Those folks eventually move to something else and adopt "C++ the good parts" instead.

dlachausse•15h ago
Swift is a great C++ and Rust alternative that doesn’t get enough attention outside of Apple platforms. It’s a performant, statically typed, compiled language that feels almost like a scripting language to write code in. It’s memory safe, cross platform, has a fantastic standard library, and has excellent concurrency capabilities. Even the non-Xcode tooling is maturing rapidly.

The big weak spot really is lack of community outside of Apple platforms.

cosmic_cheese•13h ago
I would love to see a cross-platform desktop UI toolkit for Swift, preferably one that’s reactive and imperative-dominant with declaritivity sprinkled in where it makes sense (all-in declarative design like SwiftUI hits too many language weak points for the time being). Swift is really quite nice to write once you get a feel for it, and as long as one is judicious about advanced feature use, it looks more familiar and less intimidating than Rust does which is great for newcomers.
rapsey•3h ago
Swift has IMO surpassed Rust in complexity. Rust changes very little but Swift has gone through multiple major changes and is accumulating cruft.
shim__•1h ago
Swift seems more like an Go or Python alternative
tialaramex•15h ago
I've seen this idea from a few people and I don't get it at all.

Rust is certainly not the simplest language you'll run into, but C++ is incredibly baroque, they're not really comparable on this axis.

One difference which is already important and I think will grow only more important over time is that Rust's Editions give it permission to go back and fix things, so it does - where in C++ it's like venturing into a hoarder's home when you trip over things which are abandoned in favour of a newer shinier alternative.

rich_sasha•14h ago
C++'s complexity is coming from how eager it is to let you shoot yourself in the foot. Rust will make you sweat blood to prove the bird in the sky you're shooting at is really not your own foot.
eldenring•10h ago
It's really not that bad.
bcrl•8h ago
And the gun isn't a gun, it's just a bunch of rope that you somehow got tangled into an explosive with a detonator you can't quite seem to locate.
WD-42•4h ago
You sure it doesn’t come from, for example, needing a macro just to get the length of an array?
saghm•4h ago
Yes, I think it's pretty easy to be sure that this isn't where the complexity comes from when there's literally a method to do that on arrays. I'm not even sure which language you're talking about here, because you can call `.len()` in Rust or `.size()` in C++.

If you're trying to remember what the language is where there's no immediately obvious straightforward way to get the length of an array, it's not Rust or C++; you must have been thinking of C.

tialaramex•4h ago
This is a case of exactly the "hoarder" modality in C++ that I described. When somebody says array in C++ you think of std::array, the newer shiny C++ class which you're asked to use instead of the native array types. The native array types in C++ still exist and indeed do not provide methods like size()

In Rust the arrays aren't stunted left over primitive types which weren't gifted modern features, array.len() works because all Rust's types get features like this, not just the latest and greatest stuff.

eMSF•55m ago
While it is true that only class types have member functions in C++, that does not mean that objects of other types demand the use of macros. C++ also supports non-member functions, and the standard library contains a fair amount of these; including `std::size` that can be used to "get" the length of an array.

(C++ arrays are different from arrays in many other programming languages, though not necessarily Rust, in that their type specifies their length, so in a way this is something you already "have" but certainly there are cases where it is convenient to "get" this information from an object.)

viccis•5h ago
>where in C++ it's like venturing into a hoarder's home when you trip over things which are abandoned in favour of a newer shinier alternative

Perl is so bad about this that I once worked on a very old codebase in which I could tell approximately when it was written based on which features were being used.

adastra22•5h ago
C++ has editions too btw. C++11, C++14, C++17, etc. These are opt in and allowed to break compatibility, although that is very rarely done in practice.
Expurple•4h ago
> although that is very rarely done in practice.

That's one difference. And the other important differences are:

- Rust apps can depend on library "headers" written in other editions. That's the whole deal with editions! Breaking changes are local to your own code and don't fracture the ecosystem.

- Rust has a built-in tool that automatically migrates your code to the next edition while preserving its behavior. In C++, upgrading to the next standard is left as an exercise for the reader (just like everything else). And that's why it's done so rarely and so slowly.

pjmlp•2h ago
Not really, because the crates they depend on cannot expose APIs with semantic changes across versions.

Also it requires everything to be compiled with the same compiler, from source code.

There are tools available in some C++ compilers for migration like clang, note the difference between ISO languages with multiple implementations, and one driven by its reference compiler.

Expurple•1h ago
> Not really, because the crates they depend on cannot expose APIs with semantic changes across versions.

Not sure what you're talking about. Any specific examples?

> Also it requires everything to be compiled with the same compiler, from source code.

It's not related to editions at all. It's related to not having an implicit stable ABI.

It's possible have a dynamic Rust library that exposes a repr(C) interface, compile it into an .so using one version of the compiler, and then compile the dependent "pure Rust" crates using another compiler that's just going to read the metadata ("headers") of that library and link the final binary together. Same as in C and C++. You just can't compile any Rust code into a stable dynamic library, by defalut. (You can still always compile into a dylib that needs a specific compiler version)

pjmlp•1h ago
To avoid repeating myself, here is an example from 4 years ago.

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

Expurple•54m ago
As the other commenter responded there, your example isn't about editions at all. It's about mixing ABIs and mixing multiple versions of the language runtime. Those are entirely separate issues.

You're correct that the possible changes in editions are very limited. But editions don't hinder interoperability in any way. They are designed not to. Today, there are no interoperability problems caused by editions specifically.

> compromises will be required, specially regarding possible incompatible semantic differences across editions.

That's just an assumption in your head. 4 editions later, it still hasn't manifested in any way.

tialaramex•4h ago
C++ shipping new and slightly incompatible versions of the entire language every three years isn't Editions, there was a proposal to attempt Editions (under the name "Epochs") for C++ but it faced significant headwinds and was abandoned.
pjmlp•2h ago
On the other hand, editions do less that what people think they actually do.
blub•2h ago
Because they’re both complicated languages, but for different reasons. Rust didn’t really solve memory safety, it just pushed all the complexity into the type system. If one was struggling with memory errors in C++ that’s nice. If one was using Java, that still sucks.

Furthermore some programmers really like complicated languages like Rust, Haskell, etc others like straightforward languages like Go, Python, etc.

pjmlp•2h ago
Go pushes the complexity into the programmer, that is how one ends with source code like Kubernetes, when the language doesn't provide all the tooling.

Python belongs to the complicated languages section, people that think Python is straightforward never bothered reading all the manuals, nor had to put up with all the breaking changes throughout its history, it wasn't only 2 => 3, that was the major event, every release breaks something, even if little.

Expurple•1h ago
Go is "straightforward" at the cost of making your codebase not straightforward: https://fasterthanli.me/articles/i-want-off-mr-golangs-wild-... . Programming is complex. That complexity has to live somewhere.

Python is absolutely not straighforward, it's a huge language with many moving parts and gotchas.

Although, I admit, both are very easy to start programming in and to start shipping broken projects that appear working at first. They are good for learning programming, but terrible for production.

> Rust didn’t really solve memory safety, it just pushed all the complexity into the type system.

Yes, that's what it did, and that's the right tradeoff in most cases. Where the compiler can't make a reasonable default choice, it should force the programmer to make a choice, and then sanity-check it.

> If one was struggling with memory errors in C++ that’s nice. If one was using Java, that still sucks.

It's nice for those struggling with uncaught exceptions, null pointer bugs, mutithreading bugs, and confusing stateful object graphs in Java.

blub•1h ago
Many of us strongly prefer handling some complexity ourselves that we can then tackle with tests, CI, fuzzing, etc if it means we don’t have to jump through hoops to satisfy the compiler before we can even see our code running.

Yes, Golang and Python and Java are very easy to start programming in. And unless we’re dealing with some really complex problem, like next-gen cryptocurrencies ;), by the time the Rust teams have gotten their code working and nice and proper as any Rust code needs to be, the Golang/Python/Java teams have already released to customers.

If one wants to be super-cautios and move accordingly slower to be really really sure they have no memory errors then that’s fine. There’s a market for that stuff. But selling this approach as a general solution is disingenuous.

Expurple•1h ago
> the Golang/Python/Java teams have already released to customers.

...have already released a broken prototype that appears to be working for now.

I'm yet to see a case where manually "hardening" your software is faster than writing a "similarly-good" program in Rust. That's just anti-automation. Why repeat the same work in every project and bloat your codebase, when the compiler can carry that burden for you? In my experience, Rust makes you write production-grade software faster than when using other languages.

> But selling this approach as a general solution is disingenuous.

I agree! There are legitimate cases where releasing a broken prototype as quickly as possible is important. There's room for that.

But I agrue that it's not the case for most "serious" production software that would be maintained for any period of time. And that Rust is the preferable option for writing such production software.

imtringued•11m ago
Yeah, the thing is, the moment your software has crossed the boundary of success, it becomes a burden, not a blessing. You are now stuck with it and you better have made sure that you're happy with it the way you built it, because you're not moving on from this project any time soon.

Maybe Rust isn't optimized for throwaway projects and that's fine.

imtringued•18m ago
As someone who has to work with a janky mix of C++ and Python. I would prefer getting rid of both altogether. I personally am not a fan of Python or the Python ecosystem whatsoever. It's certainly not speeding things up with those two.
pjmlp•2h ago
Because of the type system, with its ML influence, two macro systems, the stuff on nightly that many folks enjoy using, having to rely on external crates for proper error handling and async/await features.

Additionally, given its ML influence, too many people enjoy doing Haskell level FP programming in Rust, which puts off those not yet skilled in the FP arts.

Also the borrow checker is the Rust version of Haskell burrito blogs with monads, it is hard to get how to design with it in mind, and when one gets it, it isn't that easy to explain to others still trying to figure it out.

Hence why from the outside people get this opinion over Rust.

Naturally those of us with experience in compilers, type systems theory and such, see it differently, we are at another level of understanding.

Ygg2•1h ago
> Also the borrow checker is the Rust version of Haskell burrito blogs with monads, it is hard to get how to design with it in mind,

Eh. Haskell monads are a math-centric way of performing operations on wrapped types (stuff inside a monad). Rust borrow checker is way more pragmatic-centric, i.e. how can we prevent certain behaviors.

The difference being you don't see Monads being replaced by Tree-Monads, without impacting the code.

> and when one gets it, it isn't that easy to explain to others still trying to figure it out.

So is going from 0-based to X-based arrays (where X is an integer); Or learning a new keyboard layout. Just because it's hard (unfamiliar) doesn't mean it's impossible.

pjmlp•1h ago
In a way you're right, hence my last sentence.
wisty•11h ago
I'm not at all fluent at Rust, but I think c++ is not just complex, but every c++ project is complete in a different way.
bryanlarsen•10h ago
Reading between the lines, the author is a Haskell fan. Haskell is another "complicated" language, but the complexity feels much different than the C++ complexity. Perhaps I would describe it as "complexity that improves expressiveness". If you like Haskell for its expressiveness but dislike C++ for it's complexity, I suspect Rust is a language you're going to like.
fn-mote•4h ago
My impression was the opposite. I wondered how well the author knew Haskell. They mention:

(1) The "intimidating syntax". Hey, you do not even need to be using <$> never mind the rest of those operators. Perl and Haskell can be baroque, but stay away from that part of the language until it is useful.

(2) "Changes are not localized". I'm not sure what this means. Haskell's use of functions is very similar to other languages. I would instead suggest referring to the difficulty of predicting the (time|space) complexity due to the default lazy evaluation.

FTA:

> In contrast, Haskell is not a simple language. The non-simplicity is at play both in the language itself, as evidenced by its intimidating syntax, but also in the source code artifacts written in it. Changes are not localized, the entire Haskell program is one whole — a giant equation that will spit out the answer you want, unlike a C program which is asked to plod there step by step.

Edited to make the critique more objective.

andrepd•9h ago
It's really not even remotely the same. C++ has literally >50 pages of specification on the topic of initialising values. All of these are inconsistent, not subject to any overarching or unifying rule, and you have to keep it all in mind to not run into bugs or problematic performance.

Rust is a dead simple language in comparison.

blub•1h ago
As the definition says, the C++ standard is a formal technical document.

Rust doesn’t have a standard, it has a book, so you should refer to the initialization section from Stroustrup’s C++ book to keep things fair.

Expurple•1h ago
Rust doesn't need a formal document so badly, because (in safe code) the punishment for not following the rules is much more clear and small. It's either a logic bug that doesn't lead to memory-related vulnerabilities, or a readable compiler error. Of course, if your compiler doesn't catch and explain your errors to you, you need a separate book to help you with that!
Aeolun•7h ago
Rust is a lot better at producing helpful error messages than any C++ I’ve seen.
jcranmer•5h ago
Having developed a fair amount of expertise with both C++ and Rust, C++ is on a completely different level of complexity from Rust.

In Rust, for most users, the main source of complexity is struggling with the borrow checker, especially because you're likely to go through a phase where you're yelling at the borrow checker for complaining that your code violates lifetime rules when it clearly doesn't (only to work it out yourself and realize that, in fact, the compiler was right and you were wrong) [1]. Beyond this, the main issues I run into are Rust's auto-Deref seeming to kick in somewhat at random making me unsure of where I need to be explicit (but at least the error messages basically always tell you what the right answer is when you get it wrong) and to a much lesser degree issues around getting dyn traits working correctly.

By contrast C++ has just so much weird stuff. There's three or four subtly different kinds of initialization going on, and three or four subtly different kinds of type inference going on. You get things like `friend X;` and `friend class X;` having different meanings. Move semantics via rvalue references are clearly bolted on after the fact, and it's somewhat hard to reason about the right things to do. It has things like most-vexing parse. Understanding C++ better doesn't give you more confidence that things are correct; it gives you more trepidation as you know better how things can go awry.

[1] And the commonality of people going through this phase makes me skeptical of people who argue that you don't need the compiler bonking you on the head because the rules are easy to follow.

tialaramex•3h ago
The C++ 11 move semantic is definitely an example of C++ programmers being sold a "pig in a poke"† The claim in the proposal document was that although this isn't the "destructive move" which programmers wanted (and which Rust had by 2015), the C++ 11 move feature can be realised with less disruption and is just as good. In reality it left significant performance on the table and you can't get it back without significant further language change.

† This phrase would have been idiomatic many years ago but it is still used with the same intent today even though its meaning is no longer obvious, the idea is that a farmer at market told you this sack you can't see inside ("poke") has a piglet in it, so you purchase the item for a good price, but it turns out there was only a kitten in the bag, which (compared to the piglet) is worthless.

blub•1h ago
Copy by default is the right way to go. Even if less performant, it’s safe and super-easy to understand. Let the people that want to squeeze the last drop of performance worry about moves…

Move by default is the thing which complicates Rust so much.

Expurple•1h ago
Copy by default wouldn't be so bad if the move was destructive
Narew•5h ago
It's funny because I have completely the opposite stance. When I code in rust (mainly algorithm), I always struggle to change what I want to do to what rust allow me to do. And all this complexity has nothing to do with the problem.
jplusequalt•15h ago
>There is an apocryphal story about Euler in elementary school solving all the math problems that the teacher gave to the class in a jiffy, so the teacher tells him to sum up the numbers to a thousand to get him to stop pestering for more. The expectation was that Euler would go through the numbers "imperatively", like C, summing them up. Instead, what Euler did was discover the summation formula and solved it "declaratively" like Haskell, in one go, as an equation.

I've heard this story be accounted to Gauss, not Euler.

n4r9•2h ago
Yes, it's Gauss. In fact the technique is sometimes known as "Gaussian summation". The New Scientist has an article where the author chases down early references to the story: https://www.americanscientist.org/article/gausss-day-of-reck...

The earliest reference is a biography of Gauss published a year after his death by a professor at Gauss' own university (Gottingen). The professor claims that the story was "often related in old age with amusement and relish" by Gauss. However, it describes the problem simply as "the summing of an arithmetic series", without mention of specific numbers (like 1-100). Also, it was posed to the entire classroom - presumably as a way to keep them busy for a couple of hours - rather than as an attempt to humiliate a precocious individual.

lblume•1h ago
Yes. In Germany the formula n(n+1)/2 is actually called the Gaussian sum formula, or even the "small Gauss". [0]

[0] https://de.wikipedia.org/wiki/Gaußsche_Summenformel

B4uler5•15h ago
If anyone reads this and like me fears the difficulty and complexity of rust, but still wants a language that is competitive in performance, works for system level programming as well as something more general purpose definitely give Swift a go.

Over the last year I’ve started to write every new project using it. On windows, on linux and mac.

It is honestly a wonderful language to work with. Its mature, well designed, has a lot of similarities to rust. Has incredible interop with C, C++, Objective-C and even Java as of this year which feels fairly insane. It also is ergonomic as hell and well understood by LLM’s so is easy to get into from a 0 starting point.

tines•15h ago
How tied to the Mac ecosystem is Swift these days?

Also, how is its type system and metaprogramming? Does it have type polymorphism, typeclasses, macros, etc?

dlachausse•15h ago
It supports Linux, Windows, and even Android. It has all those things and more.
B4uler5•14h ago
Some of the functionalities in the core/foundation library don’t quite match between operating systems so sometimes you do need to put an “#if os(macos) do” etc, but for the most part its super straight forward working on one or another platform.

In terms of its language features it has all of those and more, sometimes too many in my opinion.

I personally favour languages that are clear in their vision. However at its core Swift is a highly performant language that is designed really well, has beautiful syntax, and in the last 5 or so years I have been impressed with its direction. It is being developed by a good team who listen to their community but not at the expense of the languages vision.

My favourite aspect of using it though is its versatility. Wether you’re working on embedded systems, a game, a web server, or even a static site generator, it always feels like the language is there to support your vision, but still give you the fine grained control you need to optimise for performance.

I also collaborate with a friend who is a Rust developer and he’s always super happy to work on a Swift project with me so I feel like that’s enough praise when you can pull a rest dev away from their beloved.

dlachausse•15h ago
Swift is the most underrated language in this space.
freeone3000•14h ago
My major problem with Swift was its error messaging. “Error: -2.” Okay, well, I suppose I’ll attach a debugger and… it’s of absolutely no help, since it crashes internally to some function and I can’t get out a stacktrace.

Function calling is irksome, with implicit parameters and mandatory parameters vaguely mixing? And the typing is appalling - there are multiple bottom types with implicit narrowing casts, one of them being NSObject, so if you’re doing any work with the Apple APIs you end up with a mess.

We got it right with Java and Rust; C++ does a passable job; why Swift had to be as incomprehensible as typescript, I cannot fathom.

saagarjha•2h ago
You should be able to get stack traces in the debugger, what issues did you run into?
JoelMcCracken•15h ago
Wow, a lot of stuff in here surprises me. C definitely can/does have spooky at a distance. Just share a pointer to a resource with something else and enjoy the spooky modifications. Changes are local as long as you program that way, but sometimes it can be a bit not-obvious that this is happening.

regarding redefining functions, what could the author mean? using global function pointers that get redefined? otherwise redefining a function wouldn't effect other modules that are compiled into separate object files. confusing.

C is simple in that it does not have a lot of features to learn, but because of e.g. undefined behavior, I find its very hard to call it a simple language. When a simple bug can cause your entire function to be UB'd out of existence, C doesn't feel very simple.

In haskell, side effects actually _happen_ when the pile of function applications evaluate to IO data type values, but, you can think about it very locally; that's what makes it so great. You could get those nice properties with a simpler model (i.e. don't make the langague lazy, but still have explicit effects), but, yeah.

The main thing that makes Haskell not simple IMO is that it just has such a vast set of things to learn. Normal language feature stuff (types, typeclasses/etc, functions, libraries), but then you also have a ton of other special haskell suff: more advanced type system tomfoolery, various language extensions, some of which are deprecated now, or perhaps just there are better things to use nowadays (like type families vs functional dependencies), hierarchies of unfamiliar math terms that are essentially required to actually do anything, etc, and then laziness/call-by-name/non-strict eval, which is its own set of problems (space leaks!). And yes, unfamiliar syntax is another stumbling block.

IME, Rust is actually more difficult than Haskell in a lot of ways. I imagine that once you learn all of the things you need to learn it is different. The way I've heard to make it "easier" is to just clone/copy data any time you have a need for it, but, what's the point of using Rust, then?

I wonder if the author considered OCaml or its kin, I haven't kept track of whats all available, but I've heard that better tooling is available and better/more familiar syntax. OCaml is a good language and a good gateway into many other areas.

There are some other langs that might fit, like I see nim as an example, or zig, or swift. I'd still like to do more with swift, the language is interesting.

tines•15h ago
> Wow, a lot of stuff in here surprises me. C definitely can/does have spooky at a distance. Just share a pointer to a resource with something else and enjoy the spooky modifications. Changes are local as long as you program that way, but sometimes it can be a bit not-obvious that this is happening.

I think the author means that the language constructs themselves have well-defined meanings, not that the semantics don't allow surprising things to happen at runtime. Small changes don't affect the meaning of the entire program. (I'm not sure I agree that this isn't the case for e.g. Haskell as well, I'm just commenting on what I think the author means.)

> IME, Rust is actually more difficult than Haskell in a lot of ways. I imagine that once you learn all of the things you need to learn it is different.

Having written code in both, Rust is quite a lot easier than Haskell for a programmer familiar with the "normal" languages like C, C++, Python, whatever. The pure functionality of Haskell is quite a big deal that ends up contorting my programs into weird poses, e.g. once you run into the need to compose Monads the complexity ramps way up.

> The way I've heard to make it "easier" is to just clone/copy data any time you have a need for it, but, what's the point of using Rust, then?

Memory safety. And the fact that this is the example of Rust complexity just goes to show what a higher level Haskell's difficulty is.

JoelMcCracken•14h ago
Thanks for explaining what you think the author meant; i meant to reiterate that I was trying to actually understand as opposed to argue, but I forgot; I think sometimes "hey I don't get what you're saying because of reasons XYZ..." comes across as "I think you're wrong".

Composing monads is another one of those painful parts of haskell. I remember being so frustrated while learning Haskell that there was all of this "stuff" to learn to "use monads" but it seemd to not have anything to _do_ with `Monad`, and people told me what I needed to know was `Monad`. Someday I wanna write all that advice I wish I had received when learning Haskell. A _lot_ of it will be about dealing with general monad "stuff".

The thing that frustrated me in Rust coming from something like Ruby was how frequently I could not _do_ a very straightforward thing, because, for example, some function is a fnOnce instead of fnMulti, or the other way around, or whatever. Here's some of the experience from that time https://joelmccracken.github.io/entries/a-simple-web-app-in-.... It became clear to me eventually that some very minor changes in requirements could necessitate massive changes in how the whole data model is structured. Maybe eventually I'd get good enough at rust that this wouldn't be a huge issue, but I had no way of seeing how to get to that point from where I was.

In contrast, I can generally predict when some requirement is going to necessitate a big change in haskell: does it require a new side effect? if so, it may need a big change. If not, then it probably doesn't. But, I've found it surprisingly easy to make big changes from the nice type system.

I really don't get when rust folks claim "memory safety" like this; we've had garbage collection since 1959. Rust gives you memory safety with tight control over resource usage; memory safety is an advantage that Rust has over C or C++, but not over basically every other language people still talk about.

If you just clone/copy every data structure left and right, then you're at a _worse_ spot than with garbage collection/reference counting when it comes to memory usage. I _guess_ you are getting the ability to avoid GC pauses, but, why not use a reference counted language if that's the problem? copy/clone data all of the time can't be faster than the overhead from a reference counting, can it??

In haskell, I did find that once I understood the various pieces I needed to work with, actually solving problems (e.g. composing monads) is much easier. I don't generally have a hard time actually programming Haskell. All that effort is front-loaded though, and it can be hard to know exactly what you need to learn in order to understand some new unfamiliar thing.

Your preferring Rust over Haskell is totally fine BTW, I'm just trying to draw a distinction between something that's hard to _use_ vs something that's hard to _learn_. Many common languages are much harder to use IME; I feel like I have to think so hard all of the time about every line of code to make sure I'm not missing something, some important side effect that I don't know about that is happening at some function call. With Haskell, I can generally skim the code and find what's important quite quickly because of the type system.

I do plan to learn Rust at some point still whenever the planets align and I need to know something like it. Until then, there are so many other things that interest me, and not enough hours in the day. I still wonder if I have really missed out on some benefit from learning to think more about data ownership in programs.

tines•14h ago
Yep I feel you. Thanks!
Expurple•14h ago
> frequently I could not _do_ a very straightforward thing, because, for example, some function is a fnOnce instead of fnMulti, or the other way around [..] It became clear to me eventually that some very minor changes in requirements could necessitate massive changes in how the whole data model is structured. Maybe eventually I'd get good enough at rust that this wouldn't be a huge issue, but I had no way of seeing how to get to that point from where I was.

I understand your frustration, and Rust does get too low-level sometimes (see https://without.boats/blog/notes-on-a-smaller-rust/). But the semantic difference between FnOnce and Fn is actually important. Fn consumes its environment and makes it unavailable later. This is an important property. When you don't want that, "just" use Fn, wrap everything in an Arc and clone everything (I understand that this is more ceremony than in other languages, and that can be unjustified).

> I really don't get when rust folks claim "memory safety" like this; we've had garbage collection since 1959.

Agree 100%! What Rust actually gives you is predictability, reliability and compile time checks, while still allowing to write relatively ergonomic imperative and "impure" code. And a sane ecosystem of tools that are designed to be reliable and helpful. I'm currently writing a post about this.

It also gives compile-time data race protection, which is still missing from some other memory-safe languages.

> I still wonder if I have really missed out on some benefit from learning to think more about data ownership in programs.

Yeah :) Affine types + RAII (ownership) allow you to express some really cool things, such as "Mutex<T> forces you to lock the mutex before accessing the T and automatically unlocks it when you're done", or "commits and rollbacks destroy the DatabaseTransaction and make it statically impossible to interact with", or "you'll never forget to run cleanup code for objects from external C libraries" (https://www.reddit.com/r/programming/comments/1l1nhwz/why_us...)

JoelMcCracken•14h ago
I asked a bad question; what I meant was specifically thinking about ownership in terms of being required everywhere and to manage memory. But there are for sure real benefits I can see for _other_ properties in certain situations, like avoiding data races that might occur in Haskell. GHC added a linear type extension, for that matter (though AFAIK its still not very great to use). But some of that seems distinct from the question "do I benefit in some data modeling way from thinking about the ownership of memory in my program" as opposed to creating/sharing references whenever convenient.
Expurple•14h ago
The deal with strict Rust-style references is that they solve mutable aliasing bugs (data races, iterator invalidation, all kinds of unexpected mutation really). That's the deal with Rust.

The whole "memory management" thing is mostly a historical accident. We could have a "smaller Rust" that auto-boxes values, has a runtime that handles reference cycles for you, and doesn't guarantee anything about the stack vs heap: https://without.boats/blog/notes-on-a-smaller-rust/

pjmlp•2h ago
When people say C is simple, besides everything that you point out, apparently they never learned anything beyond the classical K&R C book (ANSI/ISO C edition), and are stuck in a C89 mindset without any kind of compiler extensions.
Expurple•15h ago
> If someone posts a patch or submits a PR to a codebase written in C, it is easier to review than any other mainstream language. There is no spooky at a distance. [..] Changes are local.

Lol, wut? What about about race conditions, null pointers indirectly propagated into functions that don't expect null, aliased pointers indirectly propagated into `restrict` functions, and the other non-local UB causes? Sadly, C's explicit control flow isn't enough to actually enable local reasoning in the way that Rust (and some other functional languages) do.

I agree that Go is decent at this. But it's still not perfect, due to "downcast from interface{}", implicit nullability, and similar fragile runtime business.

I largely agree with the rest of the post! Although Rust enables better local reasoning, it definitely has more complexity and a steeper learning curve. I don't need its manual memory management most of the time, either.

Related post about a "higer-level Rust" with less memory management: https://without.boats/blog/notes-on-a-smaller-rust/

shmerl•5h ago
Yeah, and C can get unreadable fast. Obfuscated C contest is a great example: https://www.ioccc.org

But that doesn't mean it's a good idea to use such style for PRs, lol.

Expurple•4h ago
That's a really weird example to give. You can write unreadable code in any language if you're determined enough
shmerl•4h ago
Well, C has such contest, not every language on the other hand.
staunton•4h ago
I'd guess that's mostly because C has been around long enough to be chosen for it and people who are into that kind of thing don't urgently need more than one contest, regardless of language...
peppingdore•4h ago
Rust is unreadable by default
shmerl•4h ago
Syntax could be less terse and abbreviated, I agree. But it's not unreadable. On the other hand some complain that Rust sometimes is too verbose, so I guess it's some balance.
flohofwoe•1h ago
> But it's not unreadable.

That's just because you got used to it ;) (same as with modern C++ really, if you've used C++ long enough you become blind to its problems)

sagacity•57m ago
This is completely true.

"Regular" Rust and C++ is fairly readable, but a quick Google for "Higher Kinded Types in Rust" ends up with [0]:

  fn ap<A, B, F: Fn(&A) -> B>(x: &<Self as Plug<F>>::R, arg: &<Self as Plug<A>>::R) -> <Self as Plug<B>>::R
          where Self: Plug<A> + Plug<B> + Plug<F>;
[0] https://hugopeters.me/posts/14/
whytevuhuni•4h ago
If anything I'd like an even lower-level Rust.

There's so many good high-level languages to choose from, but when you need to go low-level, there's essentially only C, C++, Rust. Maybe Zig once it reaches 1.0.

What we need isn't Rust without the borrow checker. It's C with a borrow checker, and without all the usual footguns.

rahkiin•4h ago
It would be an interesting excercise just to see how such a language would look.

Would modules be needed or can preprocessing work still. How more advanced will the type system need to be. And how will pointers chanhe to fix all footguns and allow static borrow checking.

lelanthran•3h ago
> It would be an interesting excercise just to see how such a language would look.

I started designing one (C-with-borrow-checker) way back in 2018; never got around to finishing the design or making a MVP, but I believe you can solve maybe 90% of memory problems (use after free/double free, data racing, leaking, etc) with nothing more than some additional syntax[1] to type declarations and support for only fat arrays.

IIRC, I thought that the above (coupled with an escape hatch for self-referential and/or unsafe values) was all that was needed to prevent 90% of memory errors.

Somewhere along the way scope-creep (objects would be nice, can't leave out generics, operator overloads necessary for expressing vector math, etc) turned what would have been a small project into a very large one.

-------------------------------

[1] By additional syntax, I mean using `&` and `&&` in type declarations as a qualifier similar to how `static`, `const`, `volatile`, etc qualifiers are used.

Expurple•3h ago
> There's so many good high-level languages to choose from

We have many popular high-level languages, but I disagree that they are good. Most of them are fragile piles of crap unsuitable for writing anything larger than a throwaway script.

(In my subjective and biased assessment, which is hovewer based on professional experience)

delusional•2h ago
That's an interesting opinion. Could you mention one that wasn't fragile? Just to get a sense of the shape of these classes.
Expurple•2h ago
They are all fragile for different reasons: dynamic typing (that always leaks through bolted-on type hints anyway), implementation inheritance, null, exceptions, uncontrolled mutation, abuse of reflection and downcasts, weak leaky interfaces that the compiler doesn't check, no help with issues in multithreaded code, insecure defaults, poor semver practices in the ecosystem, poor tooling, fragile runtime dependencies.

I use Rust. From what I've read, Swift seems better than the others, with Typescript and Go following closely. All four happen to be widely praised in this thread.

To clarify, I don't have "professional experience" with every popular language, including Swift and Typescript too.

pjmlp•2h ago
Modula-2, Object Pascal, Ada,....

Zig is basically Modula-2 in C syntax clothing.

sealeck•1h ago
> What we need isn't Rust without the borrow checker. It's C with a borrow checker, and without all the usual footguns.

Which would look a lot like... Rust!

whytevuhuni•50m ago
Rust is more closely related to C++ than C.

I want Rust, but without panics, without generics (aside for lifetimes), without traits and bounds (aside for lifetimes), without operator overloading, without methods on structs, without RAII, without iterators, etc.

borkido•39m ago
What would the benefit be of not associating functions that operate on a struct with said struct? You would just end up with a bunch of functions that take a struct of that type as their first argument.
amluto•4h ago
Even ignoring undefined behavior and nulls, everything in C is mutable. Action at a distance is basically the norm.
BiteCode_dev•3h ago
And global states.

I remember the first time I was using gettext and wonder "wait, why do I have to switch the language for my whole program if I need it for just this request?" and realized that's because GNU gettext was made like that.

pjmlp•2h ago
The C myth keeps being perpetuated, sadly.

And had not GNU/FSF made C the official main language for FOSS software on their manifesto, by the time when C++ was already the main userspace language across Windows, OS/2, Mac OS, BeOS, that "It is the reason for C's endurance" would be much less than it already is nowadays, where it is mostly UNIX/POSIX, embedded and some OS ABIs.

pron•15h ago
> And the very point of writing a native program in the first place is to make it feel solid.

What does that mean, and what is it about native programs (i.e. programs AOT-compiled to machine code) that makes them feel solid? BTW, such programs are often more, not less, sensitive to OS changes.

> realizing that I was just spawning complexity that is unrelated to the problem at hand

Wait till you use Rust for a while, then (you should try, though, if the language interests you).

For me, the benefit of languages with manual memory management is the significantly lower memory footprint (speed is no longer an issue; if you think Haskell and Go are good enough, try Java, which is faster). But this comes at a price. Manual memory management means, by necessity, a lower level of abstraction (i.e. the same abstraction can cover fewer implementations). The price is usually paid not when writing the first version, but when evolving the codebase over years. Sometimes this price is worth it, but it's there, and it's not small. That's why I only reach for low level languages when I absolutely must.

Expurple•14h ago
> such programs are often more, not less, sensitive to OS changes.

You may be technically correct that they are more sensitive to the kernel interface changes. But the point is that native, static binaries depend only on the kernel interface, while the other programs also depend on the language runtime that's installed on that OS. Typical Python programs even depend on the libraries being installed separately (in source form!)

pron•14h ago
> But the point is that native, static binaries depend only on the kernel interface

Many binaries also depend on shared libraries.

> while the other programs also depend on the language runtime that's installed on that OS

You can (and probably should) embed the runtime and all dependencies in the program (as is easily done in Java). The runtime then makes responding to OS selection/changes easier (e.g. musl vs glibc), or avoids less stable OS APIs to begin with.

Expurple•14h ago
> Many binaries also depend on shared libraries.

Yeah, and those are also the opposite of "solid" :) That's why I qualified with "static". I'm so glad that Go and Rust promote static linking as the default (ignoring glibc).

> You can (and probably should) embed the runtime and all dependencies in the program (as is easily done in Java).

Congrats to the Java team and users, then. That makes it similar to the Go approach to binaries and the runtime, which I approve

pron•13h ago
> Yeah, and those are also the opposite of "solid" :)

So if that's what the author meant by "solid", i.e. few environmental dependencies, then it's not really about "native" or not, but about how the language/runtime is designed. Languages that started out as "scripting" languages often do rely on the environment a lot, but that's not how, say, Java or .NET work.

> I'm so glad that Go and Rust promote static linking as the default (ignoring glibc).

That doesn't work so well (and so usually not done) once you have a GUI, although I guess you consider the GUI to be part of the kernel.

pjmlp•2h ago
Even C has a runtime, even if tiny one.
Expurple•1h ago
I meant a runtime that has to be installed separately. It's possible to statically link a C runtime if you use musl, for example
pjmlp•1h ago
You mean like it happens on many OSes that aren't GNU/Linux?

A language runtime remains one, independently on how it was linked into the binary.

A language runtime are the set of operations that support the language semantics, which in C's case are everything that happens before main(), threading support (since C11), floating point emulation (if needed), execution hooks for running code before and after main(), delayed linking, and possibly more, depending on the compiler specific extensions.

Expurple•1h ago
You're being pedantic and trying to argue as if I misunderstand language runtimes and am speaking against language runtimes in general. That's not true. I qualified "the language runtime that's installed on that OS" from the beginning.
pjmlp•1h ago
Like on Windows for the Universal C Runtime?

I can give other non-GNU/Linux examples.

Expurple•51m ago
I don't have any negative experience with that one, but I remember having to manually install various versions of the Windows C++ runtimes to get an app working
Mawr•11h ago
> For me, the benefit of languages with manual memory management is the significantly lower memory footprint (speed is no longer an issue; if you think Haskell and Go are good enough, try Java, which is faster).

... what? Speed is no longer an issue? Haskell and Go? ??? How'd we go from manual memory management languages to Haskell and Go and then somehow to Java? Gotta plug that <my favorite language> somehow I guess...

It seems to me you have a deep misunderstanding of performance. If one program is 5% faster than another but at 100x memory cost, that program is not actually more performant. It just traded all possible memory for any and all speed gain. What a horrible tradeoff.

This thinking is typical in Java land [1]. You see: 8% better performance. I see: 28x the memory usage. In other words, had the Rust program been designed with the same insane memory allowance in mind as the Java program, it'd wipe the floor with it.

[1]: https://old.reddit.com/r/java/comments/n75pa0/java_beats_out...

ignoramous•10h ago
> What does that mean, and what is it about native programs (i.e. programs AOT-compiled to machine code) that makes them feel solid? BTW, such programs are often more, not less, sensitive to OS changes

TFA also concludes

  Since I want native code ...
I think by "solid" they mean as close to metal as possible, because, as you suggest, one can go "native" with AOT. With JS/TS (languages TFA prefers), I'm not sure how far WASM's AOT will take you ... Go (the other language TFA prefers) even has PGO now on top of "AOT".
lmm•9h ago
If they're serious about their criteria they should go with OCaml (or maybe, like, Swift, or any of dozens of languages in that space).

(Of course they actually do want Haskell but they probably need to get there gradually)

zem•9h ago
right! the table at the end just screamed "use ocaml and be happy"
legobmw99•9h ago
nobody gives OCaml a thought in these discussions. It’s such a wonderful language!
tayo42•4h ago
Does ocaml have a mature ecosystem of libraries and dependencies? And easy way to manage them? Even rust with all its hype lacks in this area imo.
lmm•4h ago
No, and that's part of why I use Scala instead. But this person is looking to make a binary to do a small thing on their desktop and does not list dependency management among their criteria.
myaccountonhn•1h ago
Depends on what you're doing and how you structure your program. It certainly does not match the ecosystem of Go, Rust or C++
sealeck•1h ago
It doesn't have a great ecosystem of libraries, but it _does_ have a good way to manage them: https://dune.build/, which as I understand it was developed at Jane Street (lots of code and dependencies) and is now open source.

> Even rust with all its hype lacks in this area imo.

This is surprising to me! I find that Rust has pretty excellent tooling, and Cargo is substantially better than the package manager in most other languages...

frou_dh•25m ago
It doesn't use curly-braces driven syntax, so will probably be accused of being "complex" and dismissed.
TOGoS•8h ago
I'm interested in the long piecewise elimination section. Presumably that's where they explain why not use Ocaml/Nim/yaddah yaddah.

If I were to write such a list, the answer would probably come down to "because I wanted to pick ONE and be able to stick with it, and Rust seems solid and not going anywhere." As much as Clojure and Ocaml are, from what I've heard, right up my alley, learning all these different languages has definitely taken time away from getting crap done, like I used to be able to do perfectly well with Java 2 or PHP 5, even though those are horrible languages.

nektro•8h ago
> If someone posts a patch or submits a PR to a codebase written in C, it is easier to review than any other mainstream language.

short-circuited reading this

brian_herman•7h ago
Deno creates binary files from typescript. https://deno.com/blog/deno-compile-executable-programs
Sophistifunk•7h ago
Sounds like a Zig-shaped hole to me ;-)
Expurple•5h ago
They complain that Go is too low-level for their needs. Zig, with its explicit allocators, is definitely even lower-level.

Rust seems low-level too, but it isn't the same. It allows building powerful high-level interfaces that hide the complexity from you. E.g., RAII eliminates the need for explicit `defer` that can be forgotten

Sophistifunk•4h ago
True, but I think the "low-level" complaint against Go in the article was just referring to all the stupid repetitive ceremony required for error handling, which Zig mostly skips over.
Expurple•4h ago
Fair enough. That's what they seem to be saying.

But then I want to chime in and argue that the repetitive syntax isn't even close to being the main problem with Go: https://home.expurple.me/posts/go-did-not-get-error-handling...

sgt•3h ago
So, while on that subject; does Zig get error handling right?
Expurple•3h ago
Idk, I'm not familiar enough with Zig to say
lblume•1h ago
It does seem to: https://pedropark99.github.io/zig-book/Chapters/09-error-han...

However errors do not seem to commonly wrapped, tagged or contextualized as is the case in Rust. This might weight lower verbosity as more important than extremely structured error handling which definitely constitutes an interesting approach.

spooneybarger•7h ago
I've written a ton of C in my life and a C lot of Go and I was rofl at the "no spooky action at distance" lines.

This was brilliant performance art. Bless your heart Dear Author, I adore you.

blamestross•7h ago
Everyone who has said the phrase "Spooky action at a distance" has been proven wrong :)
outside1234•4h ago
Rust is an amazing language once you get over the initial mental hurdle. An important thing to go in with: 99% of programs should not require you to manage lifetimes (‘a notation) If you find yourself doing this and aren’t writing a inner loop high performance library, back up and find another way. Usually this entails using a Mutex or Arc (or other alternatives based on the scenario) to provide interior mutability or multiple references. This statement might not make sense now but write it down for when it will.

I use Rust now for everything from CLIs to APIs and feel more productive in it end to end than python even.

thasso•3h ago
A nice thing about C is that you can be pretty confident that you know all major footguns (assuming you spent some time reading about it). With languages that are young or complex there is a much greater chance you’re making a terrible mistake because you’re not aware of it.
dwattttt•2h ago
I'm yet to see someone be confident in this way on anything more than a trivial program, and be right. Just way too many footguns.

My personal memorable one was bit shifting 32bit values by varying amounts, and our test vectors all failing after a compiler update, because some of the shifts were by 32. Undefined behaviour.

self_awareness•2h ago
I've seen this argument for years. "C is an easy language and it's easy to code review it.".

Maybe if you want to skip all the off-by-1 errors, double frees, overflows, underflows, wrong API usage, you don't need to maintain multiplatform build environment, and you don't support multiple architectures.

I mean, in this sense, assembly is even easier than C. Its syntax is trivial, and if that would be the only thing that matters, people should write assembly.

But they don't write assembly, because it's not the only thing that matters. So please stop considering C only in terms of easy syntax. Because syntax is the only thing that's easy in C.

junon•1h ago
> Rust, from what I've heard, has a similar abstraction level as TypeScript, perhaps even closer to Haskell but that's good, I could do with a bit more help from the compiler. But it requires me to manage memory and lifetimes, which I think is something the compiler should do for me.

Eh.... yeah? I suppose technically? But not _really_. Rust gives you the option to do that. But most programs outside of "I'm building an operating system" don't really require thinking too hard about it.

It's not like C where you're feeding memory manually, or like C++ where you have to think about RAII just right.

pavlov•1h ago
> “Rust, from what I've heard, has a similar abstraction level as TypeScript, perhaps even closer to Haskell but that's good, I could do with a bit more help from the compiler. But it requires me to manage memory and lifetimes, which I think is something the compiler should do for me.”

The Rust compiler does manage memory and lifetimes. It just manages them statically at compile-time. If your code can’t be guaranteed to be memory-safe under Rust’s rules, it won’t compile and you need to change it.

PartiallyTyped•1h ago
You can use runtime ownership structures like ref cells, arcs, etc as well.
pavlov•36m ago
Sure. The part that people often complain about is that they have to make these decisions, rather than having a runtime default picked for them by the language.
flohofwoe•1h ago
My two 'language poles' are Typescript as the 'north pole', and C as the 'south pole', with Python, C++, Zig (and to a lesser extent, Rust and Odin) placed somewhere along the latitudes.

I think that of all those options, Typescript and Zig feel closest related. Zig has that same 'lightness' when writing code as Typescript and the syntax is actually close enough that a Typescript syntax highlighter mostly works fine for Zig too ;)

sesm•1h ago
> I once spent an entire year in the heaven of C++, walking around in a glorious daze of std::vector and RAII, before one day snapping out of it and realizing that I was just spawning complexity that is unrelated to the problem at hand.

Good luck to the author with trying Rust. I hope he writes an honest experience report.

alt187•23m ago
You may want to try the criminally underrated OCaml.

It's fast, compiles to native code AND javascript, and has garbage collection (so no manual memory management).

As an added bonus, you can mix Haskell-like functional code and imperative code in a single function.