BatmanAoD
Go is a “small” language in the sense that it has an exceptionally small number of concepts (i.e. features and syntactic constructs); someone else in this thread made a comment to the effect that it takes almost no time to learn because there’s nothing to learn if you’ve already learned a different language. This is of course an exaggeration, but only slightly: Go was very intentionally and explicitly designed to be as simple as possible to learn and to use. As an example, it famously had no support for generics until almost 10 years after its 1.0 release. I think that when talking about the size of a language, some people do include the standard library while others don’t; Go has quite a large standard library, but you don’t actually have to learn the whole library or even be aware of what’s available in order to be productive.
I personally don’t think it makes sense to include the standard library in the “size” of a language for the purpose of this thread, or Boats’ original blog posts. The fundamental point is about the learning curve of the language and the amount of work it takes to produce working code, and a large standard library tends to be more convenient, not less. Common functionality that isn’t in Rust’s standard library tends to come from libraries that become almost ubiquitous, such as serde, regex, crossbeam, and itertools. From the user’s perspective, this isn’t much more or less complicated than having the same functionality available via the standard library. (Of course, a large standard library certainly makes languages more difficult to implement and/or specify; if I recall correctly, about half the size of the C++ standard is dedicated to the standard library.)
I don’t really know how to fairly compare the “size” of Rust and C++, partly because Rust is so much younger, and several C++ “features” overlap with each other or are attempts to replace others (e.g. brace-initialization as a replacement for parentheses). But I don’t think I’ve ever heard someone claim that C++ is “small” or “minimal” in this sense, so it’s in no way a good point of comparison for determining whether Rust is “small”.
Edit to add: for what it’s worth, if I weren’t quoting Boats’ blog post (which is sort of the “canonical” post on this concept), I probably would have opted for “simpler (to learn & use)” rather than “smaller.”
I do want to learn Haskell some day, but it seems like it has a whole different set of reasons why it’s tricky to learn; and I hear enough about the more complex features (e.g. arrow notation) having compiler bugs that I think it really doesn’t sound like a “smaller” or “simpler” language than Rust.
That said, yeah, it definitely meets the criteria of having strong typing, a functional style, a garbage collector, and pretty good performance.
The parts that seem likely to cause this confusion (which I shared when I first started using C++11) are:
- Moves in C++ are always a potentially-destructive operation on a reference, not just a memcopy.
- Consequently, “moving” a temporary still requires having two separate instances of the type, despite that generally not being what you want, hence RVO.
- …but move-semantics are generally presented and understood as an “optimization”, and conceptually “take the guts of this value and re-use them as a new value” is both what RVO is doing and what move-semantics are doing.
std::move
isn’t a compiler intrinsic and doesn’t force a move operation; it’s just a function that returns an r-value reference. So it makes it harder, not easier, for the compiler to “see through” and optimize away, even in the case where “as if” rule should make that legal.