3 ms·
WRT the standard library. There are tradeoffs. Yes, a big standard library that has everything you need is great, as long as it is well designed, well maintaine
by thayne 3y ago
WRT the standard library. There are tradeoffs. Yes, a big standard library that has everything you need is great, as long as it is well designed, well maintained, and has some mechanism to prevent the whole thing bloating every executable.
But executing well on that is difficult for a number of reasons:
- the release cycle of the standard library is (usually) tied to the compuler, which often means it can't evolve quickly.
- backwards compatibility is a much bigger deal for the standard library. Which means if you have a big library you will eventually have a big pile of deprecated APIs you will probably never be able to actually remove. It also feeds into the next point
- new development in stdlib can be hindered by the need to get it right the first time.
- the creators of the language probably aren't experts in every area. Which means in order to include say, a good compression library you either need to recruit someone who is an expert to write and maintain the package in your stdlib, or link to a library in another language, and the latter is still really an external depency.
- a large stdlib is a large maintenance burden
Python has a large standard library, but it has parts that are deprecated and/or largely abandoned, including packages for technologies that are no longer widely used. And its http packages are rarely used directly because third party packages like requests or urllib3 are better.
Go's standard library that is praised here isn't perfect either. The log and flag packages are often insufficient, and the implementation of net.IP is suboptimal [1].
I think probably the best balance is to start with a fairly small standard library, and when community libraries for key functionality become popular and stable, then pull them in to the standard library or otherwise make them official. And maybe have official libraries that are external to the stdlib and maybe have less rigid backwards compatibility garantees that can move faster than the language itself.
[1]: https://tailscale.com/blog/netaddr-new-ip-type-for-go https://tailscale.com/blog/netaddr-new-ip-type-for-go
- klabb3 3y ago> The log […] There’s log/slog now. Is that sufficient? > and flag packages are often insufficient […] Yes. Flag is really primitive and awkward to use. On the other hand, in a typical “imperative shell” style CLI, sharing flags between packages is not exactly crucial, which is the main reason to put it in std (interop). I’ve never really suffered from importing a 3p flag parser in my own code. > and the implementation of net.IP is suboptimal [1]. Fixed for a long time. See net/netip (although I am annoyed it’s not universally available in all net functions). It’s based on the implementation from your link.
- Arnavion 3y agoYes. The article also says: >Having a large standard library doesn't mean that the programmer shouldn't be able to swap out implementations easily as needed. But all that is required is for the standard library to define an interface along with the standard library implementation. But "Just have the standard library provide an interface" also fails when the interface itself is not guaranteed to be correct. In Rust for example, the original definition of the Future trait in the futures 0.1 crate was incompatibly different from what it eventually became in the futures 0.3 crate, and the futures 0.3 version is what was imported into libstd as `std::future::Future`. If the 0.1 version had been defined in libstd it would not have worked with async-await, so either it would've stifled async-await development, or it would have to be deprecated but still kept around for backward-compatibility alongside the newer trait.