rust func as function arg type

#rust #closure 编辑

Rust: func as function arg

在很久很久以前, 其实特么也不是很久, rust以前能直接用closure作为参数类型传参,结果现在在rustc 1.5下试了一下, 根本不行啊:

fn  call_fun(f: |i32-> i32) {        // error: expected type, found `|`
    println!("call func got res: {}", f(32));
}
fn call_function(function: fn(u8-> bool-> bool {  // fix error of the above
    function(8)
}
fn main() {
    let max = 5;
    let closure = move |arg: u8| { arg < max };
    println!("{}", call_function(closure));
}
// 
// test.rs:18:34: 18:41 error: mismatched types:
// expected `fn(u8) -> bool`,
//     found `[closure@tt.rs:17:19: 17:47 max:_]`
// (expected fn pointer,
//     found closure) [E0308]
// tt.rs:18     println!("{}", call_function(closure));
//                                         ^~~~~~~
只能说以前看到的rust语法已经在后续的发展中修改了。  
那么我们现在变成这样的做法了:
fn call_function(function: fn(u8-> bool-> bool {
    function(8)
}
fn my_local_function(arg: u8-> bool{
    let max = 5;
    arg < max
}
fn main() {
    println!("{}", call_function(my_local_function));
}

它的泛型用法:
fn call_function(function: fn(u8-> bool-> bool {
    function(8)
}
fn my_local_function(arg: u8-> bool{
    let max = 5;
    arg < max
}
fn main() {
    println!("{}", call_function(my_local_function));
    fn double(x: i32-> i32 {x + x}; // Ok
    println!("Res is {}", call_twice(10i32, double)); // OK
    
    let closure = |x: i32-> i32 {x + x};
    println!("Closure res is {}", call_twice(10i32, closure));
}
fn call_twice<A, F>(val: A, f: F) -> A where F: Fn(A)->A {
    let tmp = f(val);
    f(tmp)
}

总的说, 就是函数声明语义, 已经不能中参数类型中, 直接用匿名函数来表示参数的类型了;  
这里还有一个方式, 就是用Trait的方式, 也可以做到func as arg type:
trait FunctionCaller {
    fn call_function(&self, function: &Fn(u8-> bool-> bool;
}
struct MyFunctionCaller {
    data: u8,
}
impl FunctionCaller for MyFunctionCaller {
    fn call_function(&self, function: &Fn(u8-> bool-> bool {
        function(self.data)
    }
}
fn main() {
    let my_function_caller = &MyFunctionCaller{data: 8};
    println!("{}", invoke(my_function_caller));
}
fn invoke(function_caller: &FunctionCaller) -> bool {
    let max = 5;
    let closure = &move |arg: u8| { arg < max };
    function_caller.call_function(closure)
}