Have these prototypes the same meaning?

Hello Rustaceans,

I'm facing few understanding difficulties here.

Have these prototypes the same meaning :

fn gen_list<F: Fn(&Memo) -> ()>(self: &Self, code: F) {
...
}

and 

fn gen_list2<F>(self: &Self, code: F)
        where F: Fn(&Memo) -> () {
...
}

I also would like to confirm my correct understanding of the first prototype:
-The <F: Fn(&Memo) -> ()> has nothing to do with generics and is a kind of type alias for the type of code argument ?

-Finally: F represents a Fn traits, specialized for a Callable capturing only immutable reference on Memo structure, and returning nothing ?

Best regards.

Yes, these mean the same, it doesn't matter whether bounds are expressed when the generic parameters are declared or in a where clause.

<F: Fn(&Memo) -> ()> has everything to do with generics, since it is declaring a generic type parameter, and requiring it to implement Fn(&Memo) -> (). It isn't a type alias, since it doesn't specify a particular type. F could be a function pointer, a function item (statically referring to a single function so the compiler can optimise calls to it), or a closure type (which could include captured state).

F represents a type that implements the Fn trait with a single argument of type &Memo and a return type of () (which is a type with only a single value, used to indicate that you don't return anything meaningful).

2 Likes

Thanks for theses explanations ! :+1:

Here's a bunch of ways to shorten the signature without changing the meaning.

// Starting place
fn gen_list<F>(self: &Self, code: F) where F: for<'any> Fn(&'any Memo) -> ()

// Elided lifetimes in `Fn` traits and function pointers is a shorthand for
// functions that accept any valid lifetime
fn gen_list<F>(self: &Self, code: F) where F: Fn(&Memo) -> ()

// `<TypeVar: Bound>` is shorthand for `<TypeVar> ... where TypeVar: Bound`
fn gen_list<F: Fn(&Memo) -> ()>(self: &Self, code: F)

// `()` is the return type if none is specified
fn gen_list<F: Fn(&Memo)>(self: &Self, code: F)

// `&self` is shorthand for `self: &Self`
fn gen_list<F: Fn(&Memo)>(&self, code: F)

Someone may come along and mention one more:

fn gen_list(&self, code: impl Fn(&Memo))

But it's actually not the same as no one can name the monomoprhized F type anymore. (There may or may not be more differences in the future.)

Playground.

3 Likes

Thanks, that's helpful to have step by step evolution :slightly_smiling_face: