5 ms·
Rust also supports it, and it's actually very commonly used. For example, the function `Default::default()`, where Default is a trait that you can easily implem
by FreeFull 6y ago
Rust also supports it, and it's actually very commonly used. For example, the function `Default::default()`, where Default is a trait that you can easily implement for your own types, too.
- roca 6y agoI always thought unidirectional type inference (i.e. C++ 'auto') was good enough but I have been surprised to find omnidirectional type inference very useful in Rust... for example, constructing an empty collection to pass as the parameter to a function.
- flumpcakes 6y agoDo you have any references about "omnidirectional type inference" in rust? A quick google doesn't bring anything obvious here. I am a bit confused here, are you talking about something that would require templates in C++? template <T> auto func(T t) { return t; } y = func<int>(5);
- steveklabnik 6y agoSome people describe this split as "type deduction" vs "type inference," that is, C++ has deduction, Rust has inference. Here is the gist of it. Inferring types in C++ (and languages with type deduction) basically looks like this: auto a = something; Here, the type of a is determined by the type of something. The left hand side determines the type of the right hand side. In Rust (and languages with type inference), inferring types can look like that: let a = something; but it can also "go backwards": let a = 5; let b: u64 = a; Here, a will be a u64, because you later assign it to something of type u64, and so the compiler can "work backwards" to infer this. (In my understanding, it does not literally work backwards, but it feels like it.) To see how this plays out in your parent's comment, I adapted the code from: https://docs.microsoft.com/en-us/cpp/cpp/auto-cpp?view=vs-2019 https://docs.microsoft.com/en-us/cpp/cpp/auto-cpp?view=vs-20... #include<vector> void func(std::vector<int> &vect) { vect.push_back(30); } int main() { std::vector<int> vect; vect.push_back(10); vect.push_back(20); func(vect); return 0; } You can't say "auto vect;" there, or else gcc will say "error: declaration of 'auto vect' has no initializer". But in Rust, you can write: fn func(vect: &mut Vec<i32>) { vect.push(30); } fn main() { let mut vect = Vec::new(); vect.push(10); vect.push(20); func(&mut vect); } no type annotation on "let mut vect" there; it can see that you eventually pass it to func, and that's enough to infer the type. (For completeness, the line would be "let mut vect: Vec<i32> = Vec::new();" if you wrote out the type.
- kibwen 6y agoAn additional short-and-sweet example, using HashMap: use std::collections::HashMap; fn main() { let mut foo = HashMap::new(); foo.insert("bar", 42); } In C++, the declaration of `foo` would require a type annotation like `map<string_view, int>`.
- steveklabnik 6y ago(you need foo.insert, but yes)
- kibwen 6y agoEr, you haven't heard about Rust's new feature where it treats all common metasyntactic variable names as interchangeable? :P
- steveklabnik 6y agoHa! Well, I just realized I messed up left and right in my post so... we all do it.
- The_rationalist 6y agoBut rust doesn't even has function overloading
- deleted 6y ago[deleted]
- steveklabnik 6y agoThey’re two very different features.
- wwright 6y agoIt does, in a sense; you could say it has a “structured” way to overload functions that significantly simplifies resolution and predictability. People don’t really call it overloading, but it has many similarities.
- gpderetta 6y agotype classes, rust traits and overloading are all a form of ad-hoc polymorphism, hence the similarity.
- MaulingMonkey 6y agoRust "doesn't" have function overloading, but it effectively does: fn main() { foo((42)); foo((12.0, 13.0)); } pub fn foo(args: impl FooArgs) { args.exec() } pub trait FooArgs { fn exec(self); } impl FooArgs for u32 { fn exec(self) { println!("A number: {}", self) } } impl FooArgs for (f32, f32) { fn exec(self) { println!("{} x {} = {}", self.0, self.1, self.0 * self.1) } } https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b726f7f6e21c250aba62f9fe61e6d5a0 https://play.rust-lang.org/?version=stable&mode=debug&editio... A number: 42 12 x 13 = 156 Usually you won't abuse tuples quite like this, but it's an option. The same pattern of using traits - without the tuples - is more common [1]. Or if you need variadic functions, typically you'd resort to a macro instead. [1]: https://medium.com/@jreem/advanced-rust-using-traits-for-argument-overloading-c6a6c8ba2e17 https://medium.com/@jreem/advanced-rust-using-traits-for-arg...
- colejohnson66 6y agoWell, if it’s a trait that the type must implement (even if by the compiler), is it really overloaded? Because isn’t it technically fn Default<T>::default() -> T ? Which is polymorphism, not overloading? Idk. Maybe I’m just being pedantic?
- kibwen 6y agoRust has return type polymorphism rather than return type "overloading", but the difference only manifests for library authors; for API consumers the interface is the same either way.