Aviral Srivastava
Aviral Srivastava

Reputation: 4582

Why do we need to define the generic type with the function name other than the parameter signatures in Rust?

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

Answers (4)

RequireKeys
RequireKeys

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

stan0
stan0

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

Silvio Mayolo
Silvio Mayolo

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

do-no-van
do-no-van

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

Related Questions