3 ms·
Traits have methods. How is that not adding new functions?
by adastra22 1y ago
Traits have methods. How is that not adding new functions?
- Kranar 1y agoClasses in C++ have methods too. The problem is that you can't add new methods to an existing class.
- kbolino 1y agoMore specifically, you cannot add new abstract (aka "pure virtual") methods to an existing class/interface/trait when that class/interface/trait is already extended/implemented by code you don't control.
- bitwize 1y agoRust lets you combine multiple traits per type.
- Kranar 1y agoC++ lets you inherit from multiple classes as well. I don't see how this has anything to do with being able to add new methods to existing types.
- tomjakubowski 1y agoThere is an important difference: in Rust you can write a new trait, with new methods, and impl that trait for a type without having to change the existing structs/enums which comprise that type at all. You can also do this (with some restrictions, "the orphan rule") for types defined in another library. In C++ classes, you have to be able to modify a class definition to extend it with new methods (or a new ancestor to multiply inherit from).
- bitwize 1y agoC++ classes are types. Rust traits are applied to types.
- Kranar 1y agoAnd what exactly do you think traits apply to types exactly? If your answer doesn't start with an "m" and end with a "ethod", then you may need to re-read the Rust book found here: https://doc.rust-lang.org/book/ch10-02-traits.html https://doc.rust-lang.org/book/ch10-02-traits.html
- adastra22 1y agoYou can add traits (with their methods) to existing types, without modification.
- mrkeen 1y agoSo hypothetically, if you could add new methods to an existing class, it would solve the problem?
- Kranar 1y agoNew virtual methods, yes.
- naasking 1y ago> Traits have methods. How is that not adding new functions? If you add a method to a trait, every implementation of that trait has to be modified in the original source code. The point of the expression problem is that you want to be able to add new operations in a way that is type safe and checked for completeness, even if you don't have access to the original source code. Rust can probably do this, because its traits are equivalent to Haskell type classes and those have a solution to the expression problem, but it's not trivial. See the link in the article.
- adastra22 1y agoIn rust you would add a NEW trait, which is brought in scope by those who need it. Or add a new method to an existing trait, with a default implementation. The problem you describe makes no sense. It sounds like, for example, wanting to add a new variant to an enum while also not wanting to modify match statements which now fail exhaustive testing. That’s a direct contradiction. The only sensible charitable interpretation I can come up with is that you want to add new methods to a type without having to update any existing type definitions. This is what traits do.
- naasking 1y ago> In rust you would add a NEW trait, which is brought in scope by those who need it. No, that's not sufficient if done naively as I think you're describing. You seem to be missing the context of this discussion as described by the article. Other code already depends on the current compiled abstraction, and you want to extend it in various ways, safely, so that existing code continues to work without recompilation, but you can extend the abstraction that code is already safely handling with new types and new operations without modifying the original source code. If you want to add a new node type to an AST, with algebraic data types you would have to modify the original source code of the original functions that match on those types, so types are closed to extension. You can leave the type open to extension via traits, but now the operations are closed to extension without modifying the original source code. > It sounds like, for example, wanting to add a new variant to an enum while also not wanting to modify match statements which now fail exhaustive testing. That’s a direct contradiction. No it's not, if enums and match statements were safely open to extension rather than closed. That's exactly what would solve the expression problem. This can and has been done [1] as the article described, via multimethods or via lifting data constructors to the type class level. It's obtuse and awkward, but in theory it doesn't have to be. The ultimate goal is that the new type and/or pattern matching cases have to be provided together to cover all of missing combinations, but importantly "together" means by the time the final program is assembled and not in the source code that defined the original types or operations. [1] open pattern matching and open algebraic data types have also been done in research languages