4 ms·
Can always rely on C++ for hacks that are interesting, clever, and awful. Apparently Haskell supports overloading on return type: https://stackoverflow.com/a/4
by MaxBarraclough 6y ago
Can always rely on C++ for hacks that are interesting, clever, and awful.
Apparently Haskell supports overloading on return type: https://stackoverflow.com/a/442291/ https://stackoverflow.com/a/442291/
- FreeFull 6y agoRust 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.
- tsimionescu 6y agoI would say that, especially by C++ standards, this is surprisingly simple, easy to understand, and fully featured - even the extensible template-based version. I don't think this is even significantly more code than a Haskell version would be, and the error messages and limitations are not significantly worse either. Error messages for missing/ambigous overloads are necessarily nasty when there are many candidate overloads. And it is obvious that return-type overloading is not usable in situations where the desired return type is not known, as in the auto example. As for the template error messages, since this is just one layer of templates, I suspect that they will be quite decent - especially considering that even one std::string-related error message is easily a few lines of almost completely irrelevant gibberish (does anyone actually use non-default char_traits???).
- wott 6y ago> Apparently Haskell supports overloading on return type Ada does too.
- MaxBarraclough 6y agoI was going to include Ada in my comment, I was sure I'd read that it supports overloading on return type, but I couldn't find a supporting source with a quick google. Found a good source eventually: https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Developer/chapters/06_Functions_and_Procedures.html#overloading https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Devel...