Hacker News new | ask | show | jobs
by chabska 27 days ago
Zig, Go, and Python developers do this thing, where they announce that "We have removed the radiator fluid from the fuel tank", and all their supporters cheer about how this is good for the language, how performance will surely improve significantly, and I'm over here wondering why did they put the radiator fluid in the fuel tank in the first place.
7 comments

Sounds like you've never built something. Even with small products you have to keep correcting yourself as it's hard to foresee how each component interacts. Now try building a self-hosted C replacement lol
Programming language development have been happening for 60 years. We have tonnes of prior art, we have a rich history of experimentations. If you're a language developer that doesn't study the history, and keep making the same mistakes that other people know to avoid, I don't respect your product.

Rust language mistakes are understandable, because they do a lot of novel stuff so they encounter situations that no one have seen before. For the three languages that I mentioned, their mistakes are fairly well-known errors with obvious consequences. How hard was it to foresee that lacking generic in Go is a mistake, when the language was created well after Java had generics?

Not being sarcastic but genuine because I do not know: are there any previous languages that have a build system like Zig?

I found really cool that you have a bunch of options to configure compilation of source code itself. Not just the compiler optimization but you can automate all kinds of things: https://ziglang.org/learn/build-system/#build-system

Languages, no. But for language-agnostic package managers, Nix/Guix and Gentoo are similar.

Sadly, Gentoo is not great for managing per-project dependencies in the same way as is done by npm, pipenv, etc. Nix however works great (if you can stomach its stdlib).

Ironically Rust (hence the name) was originally billed as the language that did nothing novel at all, but just productized a bunch of concepts that were already well understood in the PL field :)

I think that a programming language — much less a programming language _ecosystem_ — is such a large space of decisions that statistically you're inevitably going to let a few of them slip. And even (as in Rust's case, initially) if you don't aim to do anything new, the combination of the interactions between features and the ways people want to use your language culturally can land you places you never anticipated when doing the initial language design. I don't think anybody in the early years of Rust could have anticipated how async would look today, for example, and IIRC Graydon Hoare still doesn't like where it ended up.

Then, there's the old software adage that the right decision for one level of adoption doesn't necessarily translate to another level. Because it's so hard to predict the impact of early decisions, early versions of programming languages are basically prototypes: your aim is to get out enough of the core differentiators of the language that people can start playing with it and _imagining_ what it will be like to work with the final thing. Part of that involves making the barrier to entry as small as possible (e.g. bundling a full build system into the precompiled compiler executable) but it also implies that you don't want to spend more time than necessary on things that work the same as other languages. If you can see the ‘obvious omission’ in the language then that means you can already imagine how it will work when that thing is implemented! As an implementor you can always flesh it out as you approach 1.0, or, if the right thing to do is so obvious and you have an enthusiastic open-source community, you can just wait for the community to build it for you.

Go's generics case is a bit different, I think. I don't claim to be an expert here (I haven't followed Go development much) but as far as I understand it the omission of generics from Go was a deliberate ideological choice: they hoped to get by with the absolute minimum of generic functionality, and the experiment was how little they could get away with and still have it adopted. (Unfortunately, I think the experiments Go was trying to run were stymied by Google and Kubernetes throwing their weight behind it, which led to a pattern of adoption that had little to do with the language design itself: we may never know what would have become of it if it had been left to stand on its own.)

Creating a C compiler is basically the assignment on plenty of CS degrees around the globe.

Plenty people do it every year, naturally nothing to compare to GCC/clang.

Creating a part of C compiler, most frequently a working optimization pass, is a regular assignment. The entirety of C compiler is too large to give it as a student assignment.
Depends which ISO C version, C89 is quite doable, and clever students might dust off a copy of "A Retargetable C Compiler: Design and Implementation" or "Compiler Design in C" as starting point.
Clever students can do anything without steering anyway ;-) Typical, I mean median, students would rather struggle to learn C.
Back on my day, high school students would learn C on introduction to programming classes, while 10 year olds were able to write Z80 or 6502 Assembly and some of them would go on to create the games industry we have today.

I guess education system went downhill since then, which I guess it is kind of true, given the poliferation of header only libraries, as if C was a scripting language.

C compiler != C replacement
C23 is a replacement for C17,...
Individual developer convenience takes priority early in projects like this, in lieu of actually thinking about the consequences of the design. It was convenient to have package management in the compiler, it meant the developers didn’t have to think about things outside their own scope - but as the language and its tooling gets wider adoption these personally-beneficial features become liabilities to adoption.

It happens in many projects .. devs will just ‘do something convenient so they dont have to do the work to do it properly’ and then that just becomes the convention, because nobody else wants to do hard work to do things properly, either.

I can accept this for a hobby project language that unexpectedly blew up in popularity. Go is not that language. Zig's developer also had grandiose plans for his project language, based on his writings, so I had expected more care put into its design.
You underestimate the difficulty of designing a language by at least an order of magnitude.

You've basically arbitrarily focused on a particular flawed design decision of a language while ignoring a thousand others that they may well have gotten right.

It's not possible to just sit down and get everything 100% right up front. The language design space has too much both depth and breadth to it.

If he had left that coupling at 1.0, I’d agree that would be careless. But he didn’t; that one expedient choice was reversed before mass adoption.

IMHO, you may be confusing “care” for legibility. The creator(s) made a choice that you disagree with and that you may not understand. They also haven’t justified or explained their choice to you. That illegibility might feel careless, even a little mean, but I reckon their focus was on figuring out the language, not seeking widespread approval.

Fair, but with all the new C-alternative languages I also see a lot of Chesterton's Fences being teared down. In part, this is also perfectly fine for experimentation, but sometimes it leaves me wondering as well.
Software is a social activity, therefore it follows social mechanics, organically. As time goes by, all these fences will need to be maintained or removed.
It is exactly because software is a social activity that one should try to understand the purpose of a design before changing it.
Well then go ahead and dig for that understanding :) From hearing interviews with some of the zig developers it's imho pretty clear, how deeply involved they are with their work.
I would agree that the zig developers know what they are doing. But not necessarily all fans of the language...
Always. Without an effort to understand, there is no social action, nor activity.

Which is why it’s so frustrating when bikeshedders use indecipherable shades of paint.

Good code is best made understood at scale .. or at least, that’s how it used to be.

Anyway I think the Zig folks are pretty clever and know what they’re doing .. I”m sure there are holes to poke in all of it, but I wonder what the big Zig projects will do with this change…

This is exactly how I feel about performance. Unrelated to any programming language, including my own optimizations. The higher the speedup the more we cheer, however most optimizations aren't clever techniques. They're just someone using a profiler to find "huh, radiator fluid shouldn't go in the fuel tank".

Most performance bottlenecks aren't inherent limitations of the hardware or the problem. There's some minimum amount of effort required to get the result, but that's never the reason why the application doesn't perform well. It's always the cruft we add on top.

One possible argument in favour of what happened here:

If you wanted to implement a package manager in the build system and keep it in the compiler, what abstraction for it would you provide between the compiler and the build system? This probably affects how you design the import system, and some other fundamental parts of your language. Those are important to get right, and probably hard you change. If you start by tightly coupling the package management and the compiler, it could be easier to design that by starting with the programmer experience you want and working backwards. Then you can change the implementation later, affecting fewer users.

I'm thinking specifically of Python here, where the import system is crazily complicated and warty, partly to accommodate all the varied ways package management was done. This compares to Go where there is a comparatively neat and small syntax for imports and the like, because they were designed with package management in mind from the start. (Not that I agree with all its design decisions.)

Hardly, Go's package management was one of first community vs Google dramas.
Which part of Zig development (I'm not asking about Go or Python right now) do you consider to be radiator fluid in the fuel tank, in this analogy of yours?
I think it's pretty obvious they are referring to package management functionality as the radiator fluid in this analogy, and the compiler is the fuel tank.
You don't think having a package management system in the compiler is weird?
I don’t know Zig or Python well enough to judge, but fwiw I don’t get this feeling at all for Go. When did that happen?
> Zig, Go, and Python

If you cherry pick, any position is possible to argue for.

What is C and error handling?

What is Java and value types?

What is C++ and modules?