5 ms·
I don't think so. Per the abstract: > All organizational functions carried out by classes can be accomplished in a simple and natural way by object inheritance
by Twisol 6y ago
I don't think so. Per the abstract:
> All organizational functions carried out by classes can be accomplished in a simple and natural way by object inheritance in classless languages, with no need for special mechanisms.
The paper replaces classical inheritance with prototypal inheritance, but it still relies on inheritance -- and more specifically, dynamic dispatch along an inheritance chain built into an object. Rust's trait system is much (much!) closer to Haskell's typeclasses, Scala's traits, and object algebras [0], all of which are essentially based on passing a set of operations on a type separately from that type itself (with various degrees of compile-time optimization and/or type-driven inference).
[0] https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf
Also from the paper:
> No special language features need to be added to support traits objects — a traits object is a regular object shared by all instances of the type using normal object inheritance. Since traits objects are regular objects, they may contain assignable data slots which are then shared by all instances of the data type, providing the equivalent of class variables.
Under static dispatch (the default), Rust's traits don't have the same recursive runtime chaining behavior. You can declare supertraits, but with static dispatch (the default) the supertrait methods are resolved at compile time anyway.
Under dynamic dispatch over "trait objects", I'm not sure about the details, but it would be reasonable to imagine that the "subtrait" contains a pointer for each supertrait. (Rather critically for Rust, trait implementations are defined statically and contain no data.) Trait objects in Rust do separate the instance data from the trait behavior in the same way that the paper suggests. The term "fat pointer" often comes up -- a trait object is a combination of two pointers, one to the instance data and one to the trait implementation for the instance. The paper refers to the trait implementation itself as the "traits object", but it's fair to call that a minor difference.
That said, the impl for a trait object can't be manually set or changed at runtime -- at least, not without unsafe arcane magic and some serious assumptions about codegen from rustc -- and Rust knows exactly what methods are available from a trait object statically, so there's no need for an inheritance-style chained dispatch. If you call a method on a trait, I'm pretty sure Rust will produce machine code that just traverses the trait impls directly to the known location of the pointer to the method you want to call. It doesn't have to check "do you know this method? no, do you know this method? no, ..."