Golang is really the best example of a minimal language (Yes yes I know late to generics and all that). I think it works because they have spent huge amounts of effort to create a well designed and fairly comprehensive standard library. The best example of this is io.Copy. You give it a reader and writer and it does an optimal copy in almost all cases.
A minimal language that doesn't have resources like Golang to put in the stdlib is just not gonna work.
Your example exposes an edge of Go that speaks to this essay.
Yes io.Copy works with any Reader and Writer but dig into the documentation and there's a runtime check for the revised ReaderFrom and WriterTo interfaces that you might also implement for faster performance. It's just something you have to know, otherwise you will not get an optimal copy.
Go 1 is right on the edge of being a big language, but what might stop it is that Google don't need it to get any bigger.
> I think it works because they have spent huge amounts of effort to create a well designed and fairly comprehensive standard library. ... A minimal language that doesn't have resources like Golang to put in the stdlib is just not gonna work.
Yes. Rust suffers from this problem. The language is now reasonably solid, but library quality and stability is all over the place. I've been annoying people in the Rust community by saying that it's time to get all widely used crates (over a million downloads, or depended upon by a widely used crate) to version 1.x. After that, no breaking changes without a major version change. Crates with re-exported types from lower levels force groups of crates into lockstep update.
The big advantage of Go is that the libraries for doing server-side web stuff are the ones used internally by Google. So they've been thoroughly exercised. The obscure case that comes up once in a trillion transactions probably happened a hundred times in the last hour in a Google server farm.
I want a step further than upgrading libraries to 1.0. I really want the Rust foundation to package up the essential libraries (bikeshedding to ensue, but something akin to Python or Go), and release those as a single, annual distribution. Even better if they could standardize the API across all of the packages, ensure minimal unsafe, etc. The `rust_stdlib_v2023` could only depend upon itself, and would be a basis for which other projects could then build from there.
It annoys me to no end the huge number of packages I pull in for doing something "simple". It is great that packages can be so small and focused, but now I have a real trust problem. How am I possibly supposed to ensure there are no malicious actors in my dependency tree?
As someone considering ramping up on Rust, this sounds disturbingly similar to the JavaScript+NPM ecosystem that is frequently criticized here.
How far along the ridiculous dependency spectrum towards NPM is crates.io?
For example, if I release a piece of nontrivial software built with Rust, how many copyright notices am I going to have to include? (To say nothing of vetting the set of transitive dependencies!)
There's already a standard library. After that, there's just whatever anybody decided to upload to "crates.io". Nothing in between. Some form of curation and quality control is needed, at least for crates depended upon by other widely used published crates.
The Rust foundation's crate manager job is apparently vacant until at least April, so nobody is officially in charge of this.
Well that is exactly what I think should change. I do not want to have to pull in a package for regex, parsing json, generating a random number, counting the number of available cpus, etc. Quite a lot of standard functionality required across a broad swath of projects. I understand Rust does not want to bring them into core, but I think there should be a middle ground that offers richer functionality to the language without the wild-wild-west of crates.io.
I think that's a great comparison. Establish a better baseline standard, but one can always reach out to a cutting edge crate if the library set is insufficient.
It's a useful comparison, although Boost has traditionally been the home of cool template code you're not supposed to understand but can use. For Rust, the problem is widely used crates such as "hyper" (http), "tokio" (support for async), and "glam" (2D and 3D vectors and matrices.) These are widely used, but not part of the standard library. They're not basic enough to be standard, and they all have alternatives. But if you use them, you need them to be stable.
For me, C-like languages like Golang don't come close to be as minimal as lisp-like languages. I agree that the standard library of Golang is smaller compared to it's contemporaries, but the language itself is not small, there is a bunch of syntax to be learned compared to languages like Clojure, where the actual language is tiny, and the standard library on the bigger side.
Technically it's true. But Lisp-like language (e.g. Scheme) is so minimal, to a point that everyone basically invented their own DSL inside it to get the jobs done. And the you ended up with a minimal language... and several sub-languages.
A language like scheme is much simpler yes, but scheme or even Common Lisp don't have anywhere near as comprehensive a lib as Golang, which is what you need to create real systems.
Even GNU make has $(filter ...) and $(filter-out ...).
It'a terrible name, by the way. A filter separates; it has two outputs. Does a function named filter return the filtrate or the residue? And I just had to look up filtrate to check which one of the two it refers to and what is the opposite term. From now on I will remember that there is residue captured in a filter, and filtrate is not that.
That would be terrible, those loops are crazy dangerous. I would avoid writing a loop and rather come up with a whole different programming paradigm. Maybe a macro system or something based on category theory?
The problem is that find first, find last, find all, filter, map, flatmap, and reduce all look pretty much the same when written as loops, and writing and reviewing any of these more than once is a poor use of time.
I agree. I've grown to really love Go the more I've used it and gotten the chance to compare it to other languages. There's a certain "completeness" and philosophical consistency to it that's really hard to find in other languages these days imo (some older languages, like Standard ML, C, Scheme, and some others also achieve this) because I think a lot of language designs now evolve more organically instead of being formally thought out up front.
Go evolved very organically. Look at the inconsistency in the way nil slices vs. maps work, for instance, or the way comparisons against nil for interfaces work. Go may be simple to explain at a high level, but the details are very complex.
A minimal language that doesn't have resources like Golang to put in the stdlib is just not gonna work.