6 ms·
Curious to know the rationale behind the "batteries not included" approach. One of the advantages of Go imho is it's solid stdlib, which includes production-re
by endorphine 4y ago
Curious to know the rationale behind the "batteries not included" approach.
One of the advantages of Go imho is it's solid stdlib, which includes production-ready HTTP server/client, JSON, XML, crypto libraries and more.
- rapsey 4y agoBecause it requires that library with that API be maintained forever. Guaranteeing it eventually becoming unused because the language is evolving and better APIs can be made. For instance mpsc and mutex libs are commonly not used because crossbeam-channels and parking_lot libraries are better than what Rust ships with.
- maxbond 4y agoIn the Python community this is called the "dead batteries" problem, and the example I like to bring up is the csv sniffer: https://docs.python.org/3/library/csv.html#csv.Sniffer https://docs.python.org/3/library/csv.html#csv.Sniffer This feature runs some heuristics and invents a new dialect of CSV based on a sample of the file. That should send chills down your spine, there is literally no safe way to use this thing. Using it in production is a bug in and of itself and will likely lead to security issues.
- pjmlp 4y agoI rather use a dead battery that somehow helps me doing my work, even if with a couple of warts, than trying to see how random package gets compiled on platform XYZ.
- maxbond 4y agoTotally understand not wanting to spend time vetting dependencies. For what it's worth, most packages "just work" on most platforms. My experience with WASM and microcontrollers is fairly limited, but I haven't had too much trouble there either. Or at least, less trouble than I would've anticipated.
- pjmlp 4y agoLets say I instal Python package for IBM I, I am sure that the standard library is supported. How many Rust packages work on IBM i? IBM i was a random example, there are plenty of platforms out there.
- maxbond 4y agoIf Rust added support for that operating system, than all of the packages that didn't rely on platform specific features would work (which is to say, virtually all of them). As it is, I'd speculate that with some fiddling you could probably get them working there today, but you'd have to repeat that every time you wanted to move to a new version of Rust. That isn't really a function of whether or not the language is batteries included, and making it batteries not included can make porting the language to new platforms simpler. But if you're working in an environment where Rust support is poor and Python support is rich, then yeah it totally makes sense to choose Python over Rust, I'm not any sort of absolutist.
- pjmlp 4y agoThat isn't the point, rather it is hit-and-miss with external libraries.
- maxbond 4y agoI've not had the experience that Rust libraries rely on platform specific behavior (ignoring things that specifically expose the capabilities of a platform specific like a HAL crate or an io_uring crate). I've had far less trouble than I anticipated getting up and running in embedded and WASM contexts. Have you had a different experience that's leading you to these views?
- pjmlp 4y agoAs mentioned, assuming rustc and cargo exist for IBM i, what will cargo build on any random project do?
- bigbillheck 4y agoPython deprecates stuff all the time. I got bit by this just last week when dusting off some old code and trying to update it from 3.7 only to find out that it's broken because stuff got moved around and now some imports don't work.
- endorphine 4y agoWith things that don't change often like JSON, XML and crypto, the same argument doesn't hold much value though.
- maxbond 4y agoThose are all use cases that are likely to have security issues; it would be nice if we could release security fixes for them without needing to bump up the release schedule of the entire language. (But this is an area where good engineers reasonably differ.)
- fiedzia 4y agocrypto does change. Maybe not specifications of specific algorithms, but which of them are supported may change. Do we want to break existing code when one of them will become deprecated or do we want to allow insecure method to be used to make web requests?
- cesarb 4y ago> > With things that don't change often like [...] and crypto > crypto does change A nearby comment mentioned Python, which did have that problem. The ssl module on its standard library didn't verify certificates by default, and since that's no longer considered good cryptographic practice (to put it mildly), that behavior had to change, even though it could break existing code. See for instance https://access.redhat.com/articles/2039753 https://access.redhat.com/articles/2039753 and the several PEPs it links to, in particular https://peps.python.org/pep-0466/ https://peps.python.org/pep-0466/ which is about the backporting of the Python 3.x version of that module to a patch release of Python 2.7.
- ohbtvz 4y ago> Because it requires that library with that API be maintained forever. Why would you say that? Do a cycle of deprecate + remove every few major releases, provide a migration path, and you're good.
- pornel 4y agoNo, Rust has a strong backwards compatibility guarantee. It can deprecate stuff, but not remove. Editions currently don't allow existence of multiple standard libraries, because code from different editions can be mixed.
- kibwen 4y agoNote that editions don't allow multiple standard libraries, but it would be possible (trivial, even) to use an edition-specific lint to deny access to a deprecated function on a newer edition. Even with that, editions don't allow you to expose two different symbols with the same name from the one single libstd so you can't easily "reclaim" or "redefine" an existing function, however since Rust already does mangling it should be possible (though potentially hairy) to expose identically-named functions that resolve to different symbols depending on the chosen edition of the crate. Neither of these things have ever been done, though they have been proposed, and it's just up to the library team to determine if they ever think it would be worth it to do so.
- nicoburns 4y agoI would absolutely love rustc to gain the ability to rename stdlib types across edition boundaries (e.g. you create a Range2 type which is named Range in Rust 2024, or vice versa). I'm not super familiar with the compiler internals, but it seems to me that it shouldn't be all that hairy. One ought to be able to deal with this in a single pass at a very early stage in the compile process. Seems like this would be a great way to deal with deprecated stdlib functionality. Especially in the case that there is a better replacement available. Ranges and channels would be obvious candidates for this.
- ohbtvz 4y ago
- kibwen 4y agoRust's standard Mutex type has been improved to the point that they're now competitive or faster than parking_lot, at least on Linux: https://github.com/rust-lang/rust/pull/95035#issuecomment-1073966631 https://github.com/rust-lang/rust/pull/95035#issuecomment-10... Channels appear to be trickier, but it might be possible to upstream crossbeam's version of those as well (it's certainly been proposed and discussed for years).
- rapsey 4y agoLocking api in std returns Result which is very annoying.
- nequo 4y agoI think the idea is that the people who write the compiler might be good at writing compilers but less good at designing HTTP or crypto libraries. So they leave that work to others. Designing Cargo was outsourced for a similar reason AFAIK.
- kibwen 4y agoYes, back in the day the goal was to provide a "batteries included" stdlib with Rust, but eventually it became obvious that good library design was hard and so almost all of the "batteries" (like rand, rustc_serialize, many of the collections, datetime, and more) were all offloaded to crates.io. As for cargo, what we have today is literally Rust's third package manager, after the experience with using the first two led people to conclude that they just needed to hire domain experts to design and implement it (the bundler folks).
- stusmall 4y agoFor me I always point to the Java's time library pre-8 as an example. It was a common pain point, experienced Java devs would know to use joda time but beginners wouldn't know to look to an alternative to the one in the standard library implementation. Over many years and a lot of pain, it was eventually replaced. If libraries are initially kept outside of the standard library they can compete, gain and lose support, and a clear winner will eventually surface. Old patterns can continue to exist and be support without breaking changes while new, better APIs can incubate. In time, after they've proved themselves, then they can be pulled into the stdlib. When it isn't included in the stdlib then a new developer needs to always ask "is this the recommended library?" In some of my projects I'm still using a few libraries that might not be the preferred community solution anymore, they are still very well supported. When a winner becomes more clear then I can migrate. It comes down to two different approaches. Both are valid, both have their advantages. I prefer rust's conservative approach to the stdlib but I understand why someone would rather less reliance on shifting 3rd party libraries.
- hyperman1 4y agoThe other side of the coin: Java had, with java.util.Date/Calendar, the basics on board. If your project grew enough to need more than the absolute basic date handling, adding Joda was easy enough. Even so, the Date class provided enough of a lingua franca that other libraries could provide dates and times to their vallers without depending on Joda. Compare it with Java's logging framework hell. java.util.Logging used to be near-unusable, and the resulting cambrian explosion of logger frameworks continues to this day. Using a library will make you depend on some logging framework. So it is today normal for a Java program to contain 4-5 different logging frameworks, passing messages to each other.
- maxbond 4y agoBoth are legitimate approaches with interesting tradeoffs, and Rust and Go are both great languages with distinct strengths. There's a sort of cathedral and bizarre dynamic at work. Go's language design decisions feel like a bizarre where people just kinda brought their ideas and they happened; think about the way you format dates in Go, it feels very much like someone just thought that up, was like "yeah that feels right", and shipped it. Their standard library is more of a cathedral; it's expansive, monolithic, and complete. Rust's language design decisions are more of a cathedral; the language feels cohesive and carefully put together, like a delicate puzzle. They're slow to adopt language design decisions, leaving them in an unstabilized purgatory until a very high degree of confidence is developed that it's the right decision. Rust's approach to dependencies is more of a bizarre; you're expected to go to crates.io and work out what dependencies to adopt for just about everything.
- ku-man 4y agoMay I kindly suggest you organize your thoughts before posting?
- maxbond 4y agoIt's on a take it or leave it basis, I try not spend too long on a comment. Some of them come out well and some don't. I thought there was something interesting enough there to share; if you didn't get anything out of it, my apologies, but I'm moving on.
- alfiedotwtf 4y agoPerl has BerkeleyDB and CGI in core. Peripheral library tastes change over time, core backward compatibility lasts a lifetime
- brundolf 4y agoSome people would say Rust has too many batteries included in the standard library (even though no_std exists) "Not enough" or "too much" is relative to your use-case. Go is almost purpose-built for web servers, whereas Rust is much more general and lower-level. It's got excellent built-ins for core data structures, async primitives, etc (which makes it much more batteries-included than C), but many (most?) of Rust's users don't need an HTTP server or JSON parsing It's a judgement call. I think they struck a pretty good balance, especially considering the vibrant ecosystem and breezy package management that can help fill in the gaps, but it's never going to be perfect for everybody's usecase
- pornel 4y ago• Rust competes with C that comes with a leaking lead-acid battery, so Rust's standard library already seems large and luxurious in comparison. • One size does not fit all. Rust targets many different environments, including embedded and WASM. A big stdlib makes porting Rust harder. It's already problematic, e.g. `std::fs` makes no sense in a browser context, and std's out-of-memory handling strategy was unacceptable for the Linux kernel. • Rust is judged by the size of its "Hello World!" executable, which already looks pretty fat due having stdlib linked statically. • Rust has a strong backwards-compatibility guarantee, which means that anything stabilized in stdlib has to stay, forever, and can't evolve. Not many features can be nailed on the first try, and not nailing them means people will forever debate whether to use the worse-but-standard version or a 3rd party version. • Rust has already dodged some bullets, because 3rd party `serde` turned out better than Rust's old built-in `rustc-serialize`, `syn` won over Rust's `syntex`, `criterion` is better than built-in `bencher`, `rand` had 8 major revisions, `time` broke compat 3 times, etc. • Rust is stuck with `std::mpsc` which turned out to be slower and less flexible than `crossbeam-channel`. • Rust team is not an infinite resource. • The Rust language is designed to be extensible via libraries, unlike Go where e.g. maps, channels, range iteration are special built-ins you can't replace.
- oconnor663 4y agoThe only other thing I'd add to this list is that Cargo and crates.io predate Rust 1.0, and that (subjectively) Cargo is an excellent package manager. So taking a dependency on 3rd party crates has always been simple and consistent in Rust, and the marginal added convenience of having something in the stdlib is smaller than in most other languages. In contrast, the Go tooling leaned pretty heavily towards monorepos and vendoring for several years, before the standardization of go.mod.