"Enumerate" in English is just a fancy word for "count" -- it means to assign numbers to a bunch of things. Which is exactly what the C concept did. The Rust usage (to mean "something that can be in one of a few different states") is new, though Java has something fairly close too.
It was a poor choice, sorry. Likewise being deliberately difficult with "trait" vs. "interface" (picking Self's jargon instead of the term that literally everyone already knows from decades of OOP) didn't serve you well. Thus we have blog posts like this needing to tell us what we probably should have been able to figure out from context.
Finally, regarding "box" vs. "block". Other languages (C# is the only one that comes to mind off-hand) have used the idea of "boxing" to imply the allocation of space for and copying of pass-by-reference data. That's sort of a different notion than simple heap allocation, so it sort of gets its own jargon I guess. I didn't complain anyway. But with Rust, a "box" really is used to refer to a dynamic heap block in any context. We sort of already had a perfectly good word for that.
Pretentious jargon isn't the worst crime in the world, but I do think Rust seems needlessly complicated in the way it likes to play Shakespeare with existing concepts.
Names are hard.
> A Rust enum isn't even "quite close" to a C enum
This is incorrect. The following Rust enum compiles down to a single byte, whose variants are represented by the numbers 0, 1, and 2: enum Foo {
Zero,
One,
Two
}
You can even give them all numeric values explicitly: enum Bar {
Ten = 10,
Eighty = 80,
TwoHundred = 200
}
And you can also just tell it where to start and let it count from there: enum Qux {
Five = 5,
Six,
Seven
}
If you throw the #[repr(C)] attribute on any of these then Rust will make sure to size them as C would on your particular platform (on my machine this attribute inflates them from 8 bits to 64 bits), making them usable directly from C as well.> Likewise being deliberately difficult with "trait" vs. "interface" (picking Self's jargon instead of the term that literally everyone already knows from decades of OOP) didn't serve you well.
But "trait" is the right term. I would agree with you if Rust traits couldn't have implementations via default methods, but they do, and interfaces usually can't (except in Java 8). Interfaces strongly suggest, well, interface, as opposed to implementation; however, traits mix and match both. You can perfectly well have traits that exist only to provide "mixin"-style implementations.
In earlier versions of Rust, traits were called interfaces (and there were separate constructs to provide implementations of interfaces), but one of the design simplifications was to unify all those concepts into one: the trait.
> Finally, regarding "box" vs. "block". Other languages (C# is the only one that comes to mind off-hand) have used the idea of "boxing" to imply the allocation of space for and copying of pass-by-reference data. That's sort of a different notion than simple heap allocation, so it sort of gets its own jargon I guess. I didn't complain anyway. But with Rust, a "box" really is used to refer to a dynamic heap block in any context.
Sorry, I just have to disagree here. I don't think anything would be simpler if the keyword were "block":
let x: Block<f32> = block 3.0;
"Block" as a verb doesn't mean "allocate" in the same way that "box" does: if anything, "block" implies something related to putting threads to sleep for I/O. And as a type, "block" sounds like a code block—i.e. something like a lambda. Ruby uses "block" for this, for instance.As does, notably, Objective-C, like Ruby due to the Smalltalk heritage.
I've never heard the term "block" used to refer to heap allocations, so I don't think it would really help.
Just go back to that tutorial with your C hat on and substitute the word "union" for "enum" and I promise it will all make sense. All your intuition about C unions will cross over just fine, and the new Rust rules (they're tagged at runtime and the compiler enforces that you can only ever use fields of a runtype-checked subtype) are straightforward extensions.
Likewise the linked blog post begins, comfortingly, with "Traits are interfaces". Once you get beyond the new jargon, you find it wraps a concept which is 95% compatible with something you've been using for years.
That the Rust team seems to find no value in this kind of naming, preferring the excess precision that comes with Create-Your-Own-Name, is what I was calling "pretentious jargon" in a previous post in the thread. It's really not that bad (I mean really, they're just names), but it doesn't speak well to where the designers heads were when they invented this stuff.
Really, that's what's starting to creep my out about Rust. Just like C++ 30 years ago, it seems like Rust has caught itself up in an internal rush (among its rock-star language nerd designers) for Masterpiece Status and sort of forgotten the goal of creating a practical tool for working programmers... At some point in the near future I have to wonder if we're going to start seeing blog posts about choosing a "sane subset" of Rust with which to develop software.
> it seems like Rust has caught itself up in an internal
> rush (among its rock-star language nerd designers) for
> Masterpiece Status and sort of forgotten the goal of
> creating a practical tool for working programmers
This is complete hogwash. Just because you disagree with the chosen terminology doesn't justify attacks on the character of the Rust developers.I'm no dummy, yet Rust is just confusing as hell sometimes. And you guys frankly don't seem to care (again: note marker "seems" to indicate a personal opinion and not a "character attack"). That turns me off. It turns lots of people off. And I don't see any significant effort being made at making it an easy tool to learn and use.
Just to name a few off the top of my head:
1. Lots of focus on friendly compiler error messages, including typo correction, automatic lifetime suggestions, and error message explanations.
2. A strong worse-is-better approach in many aspects of the language design, such as preventing reference-counted cycles (we don't try to), numeric overflow (we don't try except in debug mode), typeclass decidability (it's deliberately undecidable in corner cases to avoid complex rules), prevention of deadlocks (we don't try), userland threads (we don't implement them anymore), asynchronous I/O (it's out of the domain of libstd for now), etc.
3. Blog posts like this one to introduce aspects of Rust, as well as the tutorial.
4. The Cargo package manager, as well as crates.io.
5. Naming conventions designed to fit well with C, for example choosing "enum" over "data"/"datatype" as in ML, "trait" over "class" as in Haskell (since the latter means something totally different), but modified in some cases to avoid leading programmers of C-like languages astray (for example, "interface" changing to "trait"). This naming process has taken time, but I think Rust is in a pretty good place now. There are obviously disagreements as to the naming, but we can't please everybody.
Certainly we weren't perfect, but there was a lot of effort put into making Rust as easy to use as possible.
This is blatantly false. I've been in touch with Rust development for quite some time, and pragmatism has been paramount in all design decisions. Suggesting otherwise on the basis of disagreeing with some naming choices is complete nonsense.
This is not true. Rust enums allow you to match on which of the types you have. C unions do not. If you want to implement a switch statement over the possible members of a C union, you need to put it inside a struct with a type field. You don't need to do so in Rust, and you can't do so and have it compile.
(That said, if your real complaint is that the official docs on enums are confusing, I'd certainly agree with that.)
I'd love more specifics about which docs, if you have some time.
I had to go look it up in the reference, where it is sort of hidden too.
Specifically I ended up rewriting most of the enum page: https://github.com/geofft/rust/blob/trpl-fix-enums/src/doc/t...
I think there's more that can be done (e.g. the book doesn't document that if every variant of an enum is data-less, you can cast it to an integer), but hopefully this is a start.
They're not. Payload-less enums devolve to C enums. Rust's enum simply build the enum+union enumeration pattern into the language, and allow leaving out the "union" part.
F# actually uses box much like Rust does:
// box an int
let o = box 1
Examples:
http://fsharpforfunandprofit.com/posts/cli-types/MSDN: https://msdn.microsoft.com/en-us/library/ee340516.aspx