top | item 46752124

(no title)

BlackFly | 1 month ago

The biggest friction I experience with respect to rust closures is their inability to be generic: I cannot implement a method that takes a closure generic over its argument(s).

So then I'm forced to define a trait for the function, define a struct (the closure) to store the references I want to close over, choose the mutability and lifetimes, instantiate it manually and pass that. Then the implementation of the method (that may only be a few lines) is not located inline so readability may suffer.

discuss

order

tuetuopay|1 month ago

You most definitely can.

    fn foo<F, T>(f: F)
    where
        F: Fn(T),
        T: ToString,
    {
        f("Hello World")
    }
Or did I not understand what you meant?

armchairhacker|1 month ago

Something like this isn’t possible

    fn foo(f: impl for<T: ToString> Fn(T)) {
        f(“Hello World”);
        f(3.14);
    }

    fn main() {
        f(|x| println!("{}", x.to_string());
    }
The workaround:

    trait FnToString {
        fn call(&self, x: impl ToString);
    }

    fn foo(f: impl FnToString) {
        f.call("Hello World");
        f.call(3.14);
    }

    struct AnFnToString;
    impl FnToString for AnFnToString {
        fn call(&self, x: impl ToString) {
            println!("{}", x.to_string());
        }
    }

    fn main() {
        foo(AnFnToString);
    }

wtetzner|1 month ago

Do you have an example of this? I'm not sure I follow it exactly.