Live data from Hacker News

Abstraction without overhead: traits in Rust

blog.rust-lang.org

121–130 of 150 posts

Re: Abstraction without overhead: traits in Rust

#121
post #101

Earlier quoted context omitted.

As someone not terribly familiar with the literature but familiar with Rust's type system, I just spend a few minutes googling various pages about region based memory management (including Tofte + Talpin) as well as skimming your link (not very hard, I admit), and I don't really understand what it lets you do (that doesn't exist in a roughly analogous form in Rust). Well, there's the fact that most of the papers desc…

C++ doesn't cover the full extent of safety Rust offers at all, but there is a fair bit of overlap in how the functionality is packaged up WRT ownership types. I checked the docs and it looks like at least http://doc.rust-lang.org/0.12.0/guide-lifetimes.html#named-l... is covered which was one of my objections. I still don't like that I can't design my own linearly typed constraints, but it appears that was never a g…

I and some others are working on a rough approximation to linear types here: https://github.com/Manishearth/humpty_dumpty

A perfect implementation can be added to the language, but getting it to work perfectly with backcompat is hard so it might be made in 2.0.

Re: Abstraction without overhead: traits in Rust

#122

Earlier quoted context omitted.

I am pretty sure you can't actually construct such a type (at least not at the moment) so Rust sort of sidesteps the question.

IIRC you can.

It's early, so maybe I'm doing something stupid, but it looks like you can't! http://is.gd/9Y1HiS --- (I'm kind of surprised by the error message.)

Re: Abstraction without overhead: traits in Rust

#123
post #100

Earlier quoted context omitted.

> but you can't have a list of Show in Haskell 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]

That's not a list of Show, that's a list of a single type that instantiates Show. The difference being that in your code you can only put in a single type at a time, eg [Int] or [String], but not both Int and String under the common Show interface type.

Aha, thanks (to twic also). Now I get it!

Re: Abstraction without overhead: traits in Rust

#124
post #46

Earlier quoted context omitted.

Traits as defined in scala can actually have state and data.

Do Scala's traits change behavior depending on order of definition? That scares me tbh.

Depending on order of inheritance? Yes. And yes, it should scare you (though IME problems are rare and are obvious when they do occur). I love Scala but it's very much a language of awkward compromises.

Re: Abstraction without overhead: traits in Rust

#125

Earlier quoted context omitted.

Extra indirection? There is less indirection. With the C++ approach the data is one pointer away but the vtable is two pointers away. With the Rust approach both data and vtable are just one pointer away.

That's assuming that a "full pointer" (i.e. an unpredictable address to an arbitrary point in heap memory) is the only way to get a reference to an object. What about if you want to stick a bunch of objects in a vector, and iterate over them linearly? In the C++ approach, the data will have a nice linear cache access pattern. In the Rust approach (unless I'm missing something) you'd be storing a vector of (double siz…

How would you put or index objects in a vector in C++ if they are virtual / dynamically sized? I'm in impression that unless you have the dynamically sized object behind a pointer, you get object slicing.

Re: Abstraction without overhead: traits in Rust

#126
post #99

> What you do use, you couldn’t hand code any better. ... 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 prog…

I wouldn't call that zero-cost. It's more like variable-cost, which could be even worse than always doing virtual calls in some application types.

The average case is always as expensive or less than a virtual call. But yes, the JIT most certainly introduces unpredictability, which may be unsuitable for hard realtime applications (hard realtime Java programs employ AOT compilation for those classes that require absolute predictability).

Re: Abstraction without overhead: traits in Rust

#127
post #73

Earlier quoted context omitted.

No, Turing-completeness does not mean you can "do whatever you want". It means you can compute whatever you want that is computable. If the way you want to compute things is to embed a Rust compiler, yes you can do that, but there are many things that we'd colloquially refer to as "do whatever you want" that apply to the semantics of C++ itself. You cannot, for instance, create a new abstract base class and have a pr…

> You cannot, for instance, create a new abstract base class and have a pre-existing class in someone else's header implement your abstract base class, such that a pointer to that pre-existing class can be dynamic_cast to your class. Sure you can, for some value of base class and cast. You might not be able to use particular keywords, but data is data and math is math. You might not be able to use the built-in type s…

JS is a bad example because people who do that are preferring inheritance to composition, which is absurd.

In the case of C, yes you can do that, and where performance is critical you might prefer to do it, but it's obviously not going to be your first choice if you have any sense.

Re: Abstraction without overhead: traits in Rust

#128
post #105
post #100

Earlier quoted context omitted.

> but you can't have a list of Show in Haskell 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]

I'm not exactly sure what they mean, since the following works, and is pretty much a drop-in replacement for a Box trait object in Rust. data Showable = forall a. Show a => Showable a This allows for [Showable 1, Showable "foo", Showable 'x'] (It requires the ExistentialQuantification language feature.)

Right, this is exactly what I meant by setting up the indirection yourself. The main difference seems to be that in Haskell, you have to write this code separately for each typeclass, and wrap/unwrap it manually. In Rust, you just change Show to &Show and you get dynamic dispatch with no extra code. Here's a gist of the two approaches: https://gist.github.com/evanpw/89d89aae1159c608c476. One other difference is that in the Haskell showStatic, static dispatch is not a guarantee, just an optimization.

Re: Abstraction without overhead: traits in Rust

#129

Earlier quoted context omitted.

I am pretty sure you can't actually construct such a type (at least not at the moment) so Rust sort of sidesteps the question.

IIRC you can.

I get this when I try something like `as Box`

    error: only the builtin traits can be used as closure or object bounds [E0225]

Re: Abstraction without overhead: traits in Rust

#130
post #126

Earlier quoted context omitted.

I wouldn't call that zero-cost. It's more like variable-cost, which could be even worse than always doing virtual calls in some application types.

The average case is always as expensive or less than a virtual call. But yes, the JIT most certainly introduces unpredictability, which may be unsuitable for hard realtime applications (hard realtime Java programs employ AOT compilation for those classes that require absolute predictability).

It's a problem for more than just realtime applications. Requiring a JIT means requiring a runtime, and that makes it much harder to do thing like embed Rust libraries in scripting languages or expose a C interface.
Post reply on HN