Earlier quoted context omitted.
Lifetimes aren't regions. 4 years when it is a recapitulation of existing technology and hasn't had time to push anything forward and we already have PLs with similar facilities? That's a product-oriented rather than research-oriented direction whether you think it's too fast or not. For comparison, Haskell dates to the early 90s, based on non-strict FP languages from the 80s. ML itself started in the 70s. Much of wh…
I don't think Rust was ever intended to be primarily a research language. From what I gathered even from early docs (in Graydon's reign), it was intended to implement ideas previously introduced in research languages in a practical systems language. They even made mention of adopting only safe ideas* (and I'm too lazy to look for those quotes). I think they've had to innovate some but that wasn't the primary intent.
Abstraction without overhead: traits in Rust
91–100 of 150 posts
Re: Abstraction without overhead: traits in Rust
#92Earlier quoted context omitted.
I don't think Rust was ever intended to be primarily a research language. From what I gathered even from early docs (in Graydon's reign), it was intended to implement ideas previously introduced in research languages in a practical systems language. They even made mention of adopting only safe ideas* (and I'm too lazy to look for those quotes). I think they've had to innovate some but that wasn't the primary intent.
That would explain a lot. How do the goals contrast with C++ then? Smaller language?
In addition to memory safety, Rust's other goal was to improve the ability of programmers to reason about low-level concurrency, motivated by the enormous pain that both the Firefox and Chrome developers are currently experiencing by trying to adapt their browsers to a multicore world. The serendipitous discovery was that the same mechanism used to guarantee memory safety will also statically guarantee that your program is free of data races.
TL;DR: Rust's goals are guaranteed memory safety, guaranteed freedom from data races, and zero runtime overhead relative to C++.
Re: Abstraction without overhead: traits in Rust
#93Great article. The main bit of new information for me was that while Rust supports dynamic dispatch, its implementation has a noticeable difference from C++. In C++, the vtable pointer is in the object itself. In Rust, it's stored inside what is essentially a "fat pointer." Pointers to traits ("trait objects") are actually two pointers: the pointer to the vtable and the pointer to the actual object. This seems to hav…
It also makes multiple inheritance (which Rust has, through Java-like interfaces) easy to implement, and fast at runtime. The virtual inheritance of C++ is a real mess, by contrast [1]. [1]: http://www.phpcompiler.org/articles/virtualinheritance.html Edit: I don't mean to bash C++ here, BTW; the skinny-pointer approach has a lot of benefits when all you need is single inheritance (and there are early-stage proposals…
Re: Abstraction without overhead: traits in Rust
#94Re: Abstraction without overhead: traits in Rust
#95Earlier quoted context omitted.
It also makes multiple inheritance (which Rust has, through Java-like interfaces) easy to implement, and fast at runtime. The virtual inheritance of C++ is a real mess, by contrast [1]. [1]: http://www.phpcompiler.org/articles/virtualinheritance.html Edit: I don't mean to bash C++ here, BTW; the skinny-pointer approach has a lot of benefits when all you need is single inheritance (and there are early-stage proposals…
What is the representation for a type like Box ? Is there an extra indirection to get each of the vtables? Is there synthesized combined trait type and just one vtable pointer?
Re: Abstraction without overhead: traits in Rust
#96Earlier quoted context omitted.
That would explain a lot. How do the goals contrast with C++ then? Smaller language?
For reasons of backwards-compatibility, it's basically impossible to design extensions to C++ that make the language memory-safe by default. C++11/14 are admirable best-effort approaches to doing so, but they provide only tools for helping to enforce memory safety without providing any actionable guarantees. Rust guarantees memory safety, with the only possibility of unsafety being relegated to blocks of code specifi…
Re: Abstraction without overhead: traits in Rust
#97Earlier quoted context omitted.
Stop it, they're unions. :) Among the target market, people are going to intimately familiar with the use of "enum" and "union" from the C language. Rust's concept of a single object that can store exactly one of several types of sub-objects matches one quite closely, and not the other. Having a runtime tag and affirmative checking doesn't change the nature of the thing. We don't call "cars" something different when…
I'll have to admit enums are where I gave up the first time I read the Rust tutorial. They seem almost completely unrelated to enums in C and other languages.
Re: Abstraction without overhead: traits in Rust
#98There is always overhead when adding abstractions--the only question is whether you pay at runtime or at compile time. C++ (and presumably Rust) choose the latter, Python and Go choose the former.
Re: Abstraction without overhead: traits in Rust
#99... given you have no information about runtime behavior other than the static code.
How to achieve "zero-cost abstractions" is, as usual, a design tradeoff.
Rust -- like C++ -- lets you choose in your code whether you'd like to pay for an abstraction or not. This does produce good machine code, but has two costs: 1/ the language gets more complicated and the programmer needs to be aware of what she's paying for, and 2/ you might end up paying for stuff you end up not using (for example, all button listeners might end up being the same type, and a vtable adds unnecessary cost), so that the generated code is only optimal if you have no other information about runtime behavior.
There's another way to add zero-cost abstractions: have a single simple abstraction and a JIT to figure out at runtime -- based on observed behavior -- what the optimal machine code is. This is what the JVM does. All method calls are virtual from the programmer's perspective, and no choice needs to be made ahead of time. At runtime, the JIT views the class hierarchy and usage, and decides whether a specialized, inlined version of a function is produced or whether a vtable is actually necessary (HotSpot even makes a special case when there are exactly two implementations, replacing the vtable with an `if`). If runtime behavior changes (a new type of listener is added or even new code is loaded at runtime that adds another implementation), the JIT will notice, reconsider and recompile. So in Java, virtual or even interface method calls are also zero-cost, even though you have no choice about using them; the decision on how to implement the abstraction is done by the (JIT) compiler at runtime. This, too, is a tradeoff -- a simpler language and truly optimal code taking into consideration not only static consideration but actual runtime behavior -- at the cost of a possibly significant warmup time and possible non-optimal "mistakes" by the JIT.
Re: Abstraction without overhead: traits in Rust
#100Earlier quoted context omitted.
And typeclasses in Haskell as well.
I don't think that's true. Dictionary-passing (or something equivalent) attaches the table of methods to the functions which take typeclass instances as arguments (with extra, hidden arguments), while Rust's Box attaches the table of methods to the object pointer itself. So you can have a list of Box in Rust, but you can't have a list of Show in Haskell. You have to set up the extra indirection yourself using somethi…
I'm not sure exactly what you mean, but my naive interpretation is that you can:
Prelude> :t map show
map show :: Show a => [a] -> [String]