How to define a closure that receive a generic as a parameter?

fn main() {
    let f = |a: T|{
        println!("{}", a);
    };

    println!("Hello, world!");
}

There is no way to append generic parameters to closures, as I know.

But you can use some unstable magic

1 Like

That's still not generic though. And not that different from this:

fn main() {
    let f = |a| {
        println!("{}", a);
    };

    f("Hello, world!");
}
1 Like

You probably didn’t read my whole reply.

And no, that’s not the same. My example shows how can a trait bound be specified without generics and direct impl Trait because closures do not support both of them. Wanna remind you that usual <T> is actually <T: Sized>

Closures can “capture” generic parameters from the context they are defined in, but the closure itself can still only have a single type at a time.

So you can get a closure in a generic way, but you need to get a new closure for every new type you want to pass to the closure.

Playground


fn closure<T: std::fmt::Display>() -> impl Fn(T) {
    |a: T| println!("{}", a)
}

fn main() {
    closure()("hi");
    closure()(1usize);
}

Trying to use the returned closure with multiple types still causes an error

let f = closure();
f("hi");
f(1usize); // fails: expected &str 
6 Likes

But your example still fails this, so it's definitely not a solution to the problem generics solve.

1 Like

That’s true. I’d call it a magical crutch. Any suggestions on how can it be done better?

Unfortunately, there's no direct support for generic closures in the language, which would be required for an easy/ergonomic fix. The best one can do in this situation is to manually define a (possibly generic) type with a generic fn call<T>().

1 Like