5 ms·
If you're wondering, "What is the turbofish?", it is the awkward syntax Rust requires when specifying generic arguments in an expression, such as: Vec::<u8>:
by scott_s 6y ago
If you're wondering, "What is the turbofish?", it is the awkward syntax Rust requires when specifying generic arguments in an expression, such as:
Vec::<u8>::new()
- tooltower 6y agoIt makes me wonder. If things went differently, and if Rusty always needed this syntax for generic parameters, would the consistency have made the syntax more palatable?
- kibwen 6y agoAs in, if declaring generics looked like `fn foo::<T>()` rather than `fn foo<T>`? I dunno, at think at that point you just stop worrying about adhering to the principle of making declaration resemble use.
- tooltower 6y agoI guess I was only thinking of types, where turbofish comes up. E.g. for declaring generics, like `struct Point::<T>`.
- edflsafoiewq 6y agoIMO no. I find even :: by itself unpalatable.
- baby 6y agoIt’s also never clear where this appears, like a::<b>(c) or a::<b>::c()
- unrealhoang 6y agoin both case, `<b>` is a parameter of `a`, but in the former, `a` is a function with generic parameter and in the latter, `a` is a type with generic parameter.
- kzrdude 6y agoThe generic paramer is directly after the thing that has the parameter (it could be on the type or the method). With an exception, for enum variants it's after the variant, like None::<i32>
- __henil 6y agoI find specifying type on the left side of assignment operator much easier to interpret. > let x: Vec<u8> = Vec::new();
- adamnemecek 6y agolet x: Vec<u8> = vec![];
- deleted 6y ago[deleted]
- edflsafoiewq 6y agoSpecifically it's the ::<u8> part. It's only used when writing type parameters in an expression. let x: Vec<u8> = vec![]; // spelled Vec<u8> in "type context" let x = Vec::<u8>::new(); // spelled Vec::<u8> in "expression context"
- scott_s 6y agoYes, and googling around for this rule is what landed me on this epic poem and test.
- ruph123 6y agohttps://turbo.fish/ https://turbo.fish/
- Subsentient 6y agoAm I the only one not really bothered by the turbofish? I just think 'declarations, no colons. expressions, colons.' and that rule generally works fine for me.
- scott_s 6y agoIt's a straight-forward rule that (I think) I have mostly internalized. But coming from C++, I was initially mystified.
- vbarrielle 6y agoC++ has a rule similar to the turbofish though: #include <Eigen/Dense> // a library where I know it's required using namespace Eigen; int main() { VectorXd zeros = VectorXd::zeros(5); VectorXf zeros_float = zeros.template cast<float>(); return 0; }
- scott_s 6y agoAnd I have never internalized it! This is me, but for `typename` and `template` in expressions: https://xkcd.com/1168/ https://xkcd.com/1168/
- nzmsv 6y agoI'm sure you know better, but at first glance this seems wrong. Reason: `main` is not itself a template, so `cast` is not a dependent name. C++ compilers used to be liberal about accepting unnecessary instances of the `typename` keyword so lots of people would just sprinkle them everywhere. Modern versions of both Clang and GCC call this out. The actual rule: https://en.cppreference.com/w/cpp/language/dependent_name#The_typename_disambiguator_for_dependent_names https://en.cppreference.com/w/cpp/language/dependent_name#Th...
- vbarrielle 6y agoYou're right, since I'm frequently using templated functions I encounter this issue quite often, but here when I wanted to give an example I forgot I needed to be in a dependent context. I guess I'd better test my example next time I want to give one...