2017-03-02 51 views
0

說我有兩個功能:函數返回通用的函數指針

fn function_with_one_argument(one: i64) -> bool{ 
    one==one // irrelevant 
} 

fn function_with_two_arguments(one: i64, two: i64) -> bool { 
    one==two // irrelevant 
} 

鑑於不同的輸入值,我想返回不同的函數指針:

fn main() { 
    println!("\n\n{:?}\n\n", get_function_pointer(1)(321)); 
    println!("{:?}", get_function_pointer(2)(321/*, 321*/)); 
} 

我怎麼能代表返回一個指向不同形狀函數的指針的返回值?

fn get_function_pointer(id: i64) -> /***/(fn(i64) -> bool)/***/ { 
    match id { 
     1 => function_with_one_argument, 
     // 2 => function_with_two_arguments, /*How do we make this work?*? 
     _ => panic!("!?!?!") 
    } 
} 
+0

這兩個函數甚至沒有相同的原型。 'function_with_two_arguments'不是'fn(i64) - > bool'。你究竟想在這裏完成什麼? –

+0

@ E_net4我想改變返回類型'get_function_pointer'返回一個函數更通用的簽名。目標是動態地將不同形狀的函數作爲測試屬性進行快速檢查。 – DaveyLaser

+2

quickcheck如何調用它收到的函數? –

回答

5

您可以使用一個枚舉來表示功能

enum Either<T, U> { 
    Left(T), 
    Right(U), 
} 

fn function_with_one_argument(one: i64) -> bool { 
    one == one // irrelevant 
} 

fn function_with_two_arguments(one: i64, two: i64) -> bool { 
    one == two // irrelevant 
} 

fn get_function_pointer(id: i64) -> Either<fn(i64) -> bool, fn(i64, i64) -> bool> { 
    match id { 
     1 => Either::Left(function_with_one_argument), 
     2 => Either::Right(function_with_two_arguments), 
     _ => panic!("!?!?!"), 
    } 
} 
+0

這看起來很有希望,我會玩一下!隨着函數簽名列表的增長,它可能會有點麻煩,但是如果沒有可變參數的概念,我們可能會受到限制。 – DaveyLaser

2

的輸出下面是使用上述建議的enum後一個完整的解決方案。

extern crate quickcheck; 
use quickcheck::{QuickCheck, Testable}; 
use std::collections::HashMap; 

fn main() { 
    let mut property_map = HashMap::new(); 
    property_map.insert("one", Property::One { func: one_argument }); 
    property_map.insert("two", Property::Two { func: two_arguments }); 

    test_property("one", &property_map); 
    test_property("two", &property_map); 
} 

enum Property { 
    One { func: fn(i64) -> bool }, 
    Two { func: fn(i64, i64) -> bool }, 
} 

fn test_property(property: &str, property_map: &HashMap<&str, Property>) { 
    match property_map.get(property) { 
     Some(p) => fetch_property_and_run_quickcheck(p), 
     None => println!("No matching property in property_map"), 
    }; 
} 

fn fetch_property_and_run_quickcheck(property: &Property) { 
    match *property { 
     Property::One { func: prop_to_test } => run_quickcheck(prop_to_test), 
     Property::Two { func: prop_to_test } => run_quickcheck(prop_to_test), 
    }; 
} 

fn run_quickcheck<A>(property: A) 
    where A: Testable 
{ 
    QuickCheck::new().quickcheck(property); 
} 

fn one_argument(one: i64) -> bool { 
    println!("testing one_argument() with {}", one); 
    one == one // irrelevant 
} 

fn two_arguments(one: i64, two: i64) -> bool { 
    println!("testing two_arguments() with {} and {}", one, two); 
    one == one && two == two // irrelevant 
}