I have a function that accepts a function as an argument.
The function activates the function it accepts on another argument it’s getting.
Can I pass a trait’s function as the argument?
trait A {
fn behave(&self, s: String) -> String;
}
struct B;
impl A for B {
fn behave(&self, s: String) -> String {
return s.to_ascii_uppercase();
}
}
fn doSomething(s: String,f: fn(String) -> String) -> String {
return f(s)
}
fn useA(a: impl A) {
println!("{}", a.behave("small".to_string()));
}
fn main() {
let b = Box::new(B);
useA(*b);
doSomething("small".to_string(), b.behave); <--- dosent work
}
The code in the last line produces the following error:
error[E0609]: no field behave on type Box
my question is can I achieve this kind of functionality.
I’ve tried also static function inside the trait’s definition and did not succeed.
Thanks!
>Solution :
First, don’t use the function pointer type fn unless you absolutely need to. In nearly all cases, you’ll use the Fn/FnMut/FnOnce traits. You will need to decide which one you need based on your situation. For example, Option::map uses FnOnce, while Iterator::map uses FnMut. Fn is usually used when you want to store the closure and use it immutably. In this case, you would use FnOnce.
fn doSomething<F: FnOnce(String) -> String>(s: String, f: F) -> String {
return f(s)
}
Second, you can’t create a partially applied function like with b.behave. Instead, you can make a closure.
let func = |s| b.behave(s);
doSomething("small".to_string(), func);