The syntax and meaningful spaces are annoying. The dynamic typing is abused to hell in everything including the standard library. It has wacky paradigms like "exceptions instead of conditionals" or having "else" clause for loops.
It lacks decent packaging and by design cannot handle multiple versions of dependencies or perform metadata-only/declarative resolution. To resolve the dependencies of a Python package you need to install it. Many Python packages resolve their dependencies imperatively depending on the current system state. When you need binary dependencies like numpy it gets even worse since libpython doesn't have a stable ABI.
It is one of the most underdesigned languages but it holds a dear place due to being easier to translate from pseudocode to actual implementation. This resulted many academics to pick it up and write advanced math libraries in it.
Oh gosh, the choice of language is such a context-specific design decision. The first versions of what became Docker were written in Python. The choice of Go was a mix of nerdy excitement ("it's like the best of Python and C!"), and adoption strategy: back then devops tools were segmented by language runtime: ruby, python or Java mostly. Shipping a compiled binary allowed us to be adopted by all tribes.
None of these things can be transposed today, so I guess I can't answer...
For what it's worth, my current project (dagger) is written in Go.
The article's point that Go is a bad fit for some of the low-level interactions with the kernel, is absolutely correct though. We had to do a lot of juggling to get it to work properly. But in the end it was fine. I would say it was the correct choice of language at the time, and it certainly contributed to Docker's early success.
Another explicit goal was to facilitate contribution. We thought Go syntax was "vanilla" enough to attract a broader set of contributors than a more niche, opinionated language like Erlang, Haskell, Clojure etc. I think that also worked out well - Docker was known for attracting many contributors, many of them making their very first open source contributions. We even ran special meetups to help people become contributors, that was fun.
I think that's so true and it was one of the keys to success of the project. I contributed the very first simplistic implementation of referencing linked containers by name. I never would have bothered if the project was written in C or C++ (I'm more than capable, I just don't enjoy torturing myself). Go made it MUCH easier for a fly-by-night contributor such as myself to join the party.
You can also design a "dual-pass" API. Basically you have an API call to estimate or calculate the memory usage needed and then another parameter / API call to actually do the operation.
For example the WideCharToMultiByte [1] function of Win32 handles UTF-16 to UTF-8 conversion. If you pass your destination pointer as NULL, then it purely calculates the number of bytes you'll need in your buffer. Then the main program actually allocates the memory and calls it again with the populated destination pointer.
> Also, the optimism just highlighted how out of touch they were, that they thought people would actually just rewrite everything in 5 years is bizarre and suggests a fundamental lack of understanding to me. Same thing with Wayland and GPLv3 to me.
It is the fundamental difference in the developer's origin/experience in FOSS projects vs commercial software. However, there is an even bigger paradigm difference underneath. Academia survives on one-off projects and FOSS is often recruits students in universities who contribute as hobby, without contracts. The usual POSIX software is all about exposing things with minimal abstractions. It makes developing and iterating on software easier on the developer.
People who work in commercial software are forced into decade-long support contracts. So they develop skills in managing long-term backwards compatibility. This comes with the abstractions and software designs with more thought into their future.
You see that in Windows components that the engineers thought about how the computer systems will evolve and allocated some slack to extend the software: https://faultlore.com/blah/c-isnt-a-language/#case-study-min... . This kind of hindsight isn't something one can easily learn without being forced into the backwards compatibility and getting burned before or mentored. Some of the skills also means that you need to learn where to place the "narrow waist" of the API.
To illustrate the difference I'll actually compare Win32 vs X11/Wayland. Win32 is a much better abstraction and much better "narrow waist" point than X11 was. X11 was designed tightly around 80's hardware and people had to add hacks on top of hacks to actually make things like GPUs work. X11's network transparent architecture actually made implementing direct rendering harder. While Win32 already had some ideas that made into Wayland and it designed nice abstractions for allocating windows, direct rendering buffers and compositing. Win32 had baked in concepts like a window or a button or text rendering. So when the devices with HighDPI appeared or when new security boundaries needed the higher level abstractions of Win32 made it possible for Microsoft to make smaller API changes while the whole X11 started to collapse with 90s hardware and then was useless for 2010s.
> It is the fundamental difference in the developer's origin/experience in FOSS projects vs commercial software. However, there is an even bigger paradigm difference underneath. Academia survives on one-off projects and FOSS is often recruits students in universities who contribute as hobby, without contracts. The usual POSIX software is all about exposing things with minimal abstractions. It makes developing and iterating on software easier on the developer.
I think it's just the fundamental mentality of the kind of people it recruits and it wasn't always the case either. It felt like the old Unix guard of people who worked at Bell Labs were far better adjusted. If anything, this feels more like a social thing because you just encounter these kinds of people a lot outside of programming on say Reddit or 4chan, as in people who just completely seem to miss what goes on outside of their little bubble and I do feel certain types of FOSS have a higher chance of recruiting those people because they were the people who used to first submit patches for free on github and then rose the ranks. This does not in any way occur with say people being paid by Intel to write drivers for Linux. They seem to know perfectly well what goes on with the world because they weren't recruited through those channels that are just more likely to attract, shall we call it “terminally online” people as the kids call it nowadays?
> To illustrate the difference I'll actually compare Win32 vs X11/Wayland. Win32 is a much better abstraction and much better "narrow waist" point than X11 was. X11 was designed tightly around 80's hardware and people had to add hacks on top of hacks to actually make things like GPUs work. X11's network transparent architecture actually made implementing direct rendering harder. While Win32 already had some ideas that made into Wayland and it designed nice abstractions for allocating windows, direct rendering buffers and compositing. Win32 had baked in concepts like a window or a button or text rendering. So when the devices with HighDPI appeared or when new security boundaries needed the higher level abstractions of Win32 made it possible for Microsoft to make smaller API changes while the whole X11 started to collapse with 90s hardware and then was useless for 2010s.
Even ignoring the future though. It's just the understanding of the “now”. Things like initially libinput having no way to disable mouse acceleration and the developer at first resisting it until receiving a mountain of complaints and finally relenting because “Everyone would want mouse acceleration always on, right?”. Or just in general how these people seem to completely forget that desktop usage is largely just an afterthought for Linux and the main usages are phones, servers, small devices and supercomputers. To them Linux is really just a desktop kernel and they completely don't seem to realize that desktop usage of it is really super inconsequential in the larger scheme of things.
> Or just in general how these people seem to completely forget that desktop usage is largely just an afterthought for Linux and the main usages are phones, servers, small devices and supercomputers.
I think you're right in that most paid developers use/develop for Linux ecosystems do for server or embedded, where they use Linux out of "laziness" since it provides a basics. Then the engineering team implements everything else GUI, webservers etc on top of it. At work I'm a firmware engineer but I can also write quite complex Linux stuff and I occasionally contribute to the Yocto recipes. You really see that Linux ecosystem is really for people who prefer to dig stuff. Dig decade-old email threads, read C source the whole time. Fix and patch weird bugs and pile workaround on top of workaround by forking things. Linux ecosystem really isn't designed to scale to be deployed into wild-west PC universe and still lives in a "here is the source; good luck!" world.
> Even ignoring the future though. It's just the understanding of the “now”. Things like initially libinput having no way to disable mouse acceleration and the developer at first resisting it until receiving a mountain of complaints and finally relenting because “Everyone would want mouse acceleration always on, right?”.
I mean it can be argued where to split and keep libinput as the lower-level library for the embedded engineers (TBH I don't know if embedded engineers really care). However, what I don't understand is: if they are going to split things in a more granular way, why not provide a higher level library for DEs where functions for acceleration etc. are provided as extras.
At the same time, I have a hunch that GNOME could be the reason (AFAIK libinput dev is employed at RedHat with other GNOME devs) and GNOME likes things "lean" i.e. featureless. One of the reasons Wayland has completely surrendered window decoration and we have to use workarounds and hacks like XDG Decoration is GNOME's insistence on offloading everything to clients and vetoing every single compromise (including XDG Decoration, but Valve pushed it AFAIR).
Again I think designing Wayland as a "allocating rectangles on CPU or GPU buffers" protocol/library is okay. But why don't we have a unified higher level "Wayhill" where ex-GNOME DEs define things like what a decorated window is [^], what happens to the crashed application, unified resizing, actual display management and unified configuration so it can be shared with the login manager. Now KDE implements one thing, wl-roots implements another (wl-roots is probably closer to my "Wayhill" idea but it kind of caters to more terminal-driven stuff, I do prefer pure GUI-driven desktops) and GNOME just opposes everything.
I see this kind of "provide the lowest level abstraction, nothing else" as a paradigm in every single component in Linux. It is really tiring both as a desktop user and as a paid developer. Since it is a socio-technic concept, rather than a purely technical, I don't really see that we'll solve it with "more FOSS". The overall mindset needs to change or we need to bootstrap a new ecosystem (which is an uphill battle).
[^]: Yes Firefox and Chrome would look wacky (basically dual decorated) since they use some lower level GNOME/GTK stuff (file dialogs, cairo rendering etc, GTK themes/libadwaita), however this kind of push could have helped browsers to be more agnostic as well.
They basically had a cart populated with random-ass stuff they found in computer shops to the maximum of the USB spec supported wirh hubs. They inserted the hub and watched Windows crash until everything is fixed and worked, then they started yanking it when it was still discovering devices.
Sorry but scientific method has been the default for "Truth" for many academic subjects. It is reliable and idempotent. If all of the human information and most of the knowledge workers are removed from the Earth tomorrow, many will arrive in the same conclusion in most of the natural sciences and maths. The language and representation will be different but prime numbers will still be prime numbers and the matter will still be made of one neutral and two "interactive" elements.
Social sciences like politics, history and economy are harder to replicate with the scientific method, however repeated observations, statiscial information as well as qualitative analysis with evidence-based research can still provide replicable analysis.
> If anyone has a better idea how to determine what is true and what isn't - i'd certainly be very interested
This kind of excuse is often cited to shut down any discussion, especially in history, politics and economics. I find it deeply anti-intellectual and dogmatic. As long as evidence and counter-evidence is followed, it should be possible to discuss alternative interpretations and solutions.
While I agree with your sentiment, I must add to this that to say that something is unequivocally true that holds in all conditions everywhere is difficult to ascertain in general. So we have to deal with that two (or more) things can be true at the same time (sometimes). This may be less the case for things such as prime numbers but more the case when the underlying principle is void of simple cause and effect (in the linear sense).
The scientific method can be used to falsify hypotheses. It cannot prove that something is true. Fields that use the scientific method typically rely on social consensus for determining the truth. Empirically speaking, the social consensus seems to converge to a reasonable approximation of the truth with a high probability, but the process can take decades.
> This kind of excuse is often cited to shut down any discussion, especially in history, politics and economics. I find it deeply anti-intellectual and dogmatic. As long as evidence and counter-evidence is followed, it should be possible to discuss alternative interpretations and solutions.
How do you propose to discuss "alternative interpretations and solutions" if you believe that doing so is "anti-intellectual and dogmatic".
I'm honestly confused how you could respond this way to my comment. It sounds like you are criticizing yourself (?)
Open knowledge systems like Wikipedia are not really defensible. Letting anybody edit any page is a great way to get AI and human slop everywhere. It makes it extremely easy to insert knowledge with dubious quality and sources.
We need "open access" knowledge systems with known authors who are sponsored by non-profit and educational organizations and its their duty to defend their reputation.
Humanity needs more openly accessible curated and factually checked information and "open to modify" systems are bad at in all.
I used to edit Wikipedia as a hobby with the goal of getting as many incorrect facts in it as possible, and seeing how long they lasted before being corrected. These were really minor things that hardly anyone would care about so they would often fly under the radar. I think my longest lived fake fact was around five years. Was quite pleased with that. Eventually I got bored and moved on but it was a great game while it lasted.
>Letting anybody edit any page is a great way to get AI and human slop everywhere.
but that's not how Wikipedia works. articles about noteworthy or controversial things have activist commissars and/or paid shills watching every edit, and unless your edit aligns with the narrative they wish to present, it will be undone with essentially "because fuck you" as the reason.
its value is still considerable, of course -- there are far more neutral things than controversial ones, and most of the articles about those are fine. everything even remotely political, however, is thoroughly subverted.
What kind of Rust projects? How many dependencies? Does it use macros? How about generics and traits?
Most of the Rust ecosystem makes unnecessarily heavy use of compile-time traits and monomorphized generics (aka Go generics or C++ templates). The language syntax encourages it as well. The thing is compile times will NEVER drop to level of Go unless the entire set of players (language, standard library, almost all library developers) actually prioritize dynamic dispatching instead of static dispatching / monomorphization. That's the tradeoff for the performance and RAM usage you gain. Template-heavy C++ also suffers from the same issues for the same reason.
Golang is fast to compile because its interface definitions are runtime/dynamically dispatched (aka `&dyn Trait` in Rust or virtual classes in C++) and it had no generics for a long time forcing types like slices, map and vectors to be magic types.
If you need fast compile times, you need to split your program into multiple binaries or write your own backend ecosystem that almost only uses dynamic dispatching. If your full Cargo dependency tree pulls 50+ crates, you'll not get fast compile times. You need to avoid derive-macros like plague. You need to use non-Cargo build systems or `build.rs` to generate Rust code instead of derive-macros.
Unlike Golang Rust also targets extremely memory constrained devices where monomorphization enables memory savings, extra optimizations and fewer CPU cycles / instructions (e.g. microcontrollers, UEFI/BIOS implementation). It is a system programming language first. With system programming languages you are responsible for these choices as the developer. Rust just happens to have a vivid scene of backend libraries since the language's safety enabled many non-system developers to write correct and performant programs quickly.
This is a bit of a tangent, but Go generics aren't monomorphized. Each instantiation is "stenciled" down to its GC shape and then the differences among types with the same shape are handled using a "dictionary" which is kind of like Swift's witness tables or Go's own interface vtables. See this description for details: https://github.com/golang/proposal/blob/master/design/generi...
The typical end result sits somewhere between monomorphization and type erasure in terms of generated code and runtime indirection.
Oh good to know and I stand corrected. I guess if you can opt-in with a syntax (like dyn does in Rust), this kind of in-the-middle generics could be a nice addition to systems programming languages. However, we need a GC-less solution of course.
> The axiom is “monomorphic data, polymorphic code”. In other words, unlike languages like Haskell and OCaml that generally rely on uniform representations (boxing) to enable polymorphic code generation, data layouts will stay the same under polymorphization, and only function ABIs will change. [...] Go’s gcshape is somewhat analogous to our concept of data layouts.
> A whole program is compiled in a single step, without intermediate linking. This makes incremental development much slower for large programs but enables far more optimization opportunities. We are actively working on build caching so that at least part of the work does not need to be redone on every compilation.
It lacks decent packaging and by design cannot handle multiple versions of dependencies or perform metadata-only/declarative resolution. To resolve the dependencies of a Python package you need to install it. Many Python packages resolve their dependencies imperatively depending on the current system state. When you need binary dependencies like numpy it gets even worse since libpython doesn't have a stable ABI.
It is one of the most underdesigned languages but it holds a dear place due to being easier to translate from pseudocode to actual implementation. This resulted many academics to pick it up and write advanced math libraries in it.
reply