Reputation: 4582
Going over the generic types chapter of the official Rust book, I noticed that we have to define the generic function as follows:
fn largest<T>(list: &[T]) -> T {
My doubt is: why add <T>
right after largest
? We don't do that for non-generic functions such as: fn largest(list: &[i32]) -> i32
.
Upvotes: 2
Views: 788
Reputation: 538
For the same reason we write <T>
after generic implementations. For example impl<T> SomeGenericStruct<T>
. If you didn't mark the implementation, or in the case of your question, your function, as a generic with the <T>
syntax, which is also required of lifetimes such as <&'a T>
, then the compiler wouldn't treat T
as a generic.
Upvotes: 0
Reputation: 11807
I'd say the <T>
syntax introduces the type T
in scope so it can be used for parameter types and return type. If you didn't mark the function with <T>
how would it know what T
is? It would rely on the type being visible already which is the case for the non-generic function you provided - i32
is imported by default.
Upvotes: 2
Reputation: 70267
They mean two different (and equally valid) things
fn largest<T>(list: &[T]) -> T
This says "largest
is a function that, for any type T
, takes a slice of T
and returns a T
". On the other hand,
fn largest(list: &[T]) -> T
This function says "largest
takes a slice of T
and returns a T
", where T
is some specific type in scope. That is, this second definition assumes there's something of the form
struct T {}
or some other type declaration, alias, or import in scope right now, and largest
only works for that type. Note that T
is a horrible name for a specific type, but Rust doesn't care about good names. As far as Rust is concerned, T
is a perfectly valid type. So is ndscjkdbhsgey
, but please don't name your structs that either. We need the <T>
to tell Rust "this is not a specific type name; it's a variable, and I'm choosing to call it T
".
Upvotes: 9
Reputation: 236
Because you have to create the generic type T
. i32
is a predefined type while T
is one that only exists within the context of that function and you have to define it like a variable for the compiler. It does not have to be T
and you could have made the function definition be fn largest<U>(list: &[U]) -> U
.
Upvotes: 3