【问题标题】:Function that returns generic function pointers返回通用函数指针的函数
【发布时间】:2017-03-03 23:14:52
【问题描述】:

假设我有两个功能:

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!("!?!?!")
    }
}

【问题讨论】:

  • 这两个函数甚至没有相同的原型。 function_with_two_arguments 不是 fn(i64) -> bool。您究竟想在这里实现什么目标?
  • @E_net4 我想更改返回类型get_function_pointer 以返回更通用的函数签名。目标是动态地将不同形状的函数作为测试属性提供给快速检查。
  • quickcheck如何调用它接收到的函数?
  • 你不能用单个数组或结构替换传入的参数吗?
  • @ChrisEmerson quickcheck 需要一个函数where function is Testable。来源在这里:github.com/BurntSushi/quickcheck/blob/master/src/tester.rs

标签: rust


【解决方案1】:

可以使用枚举来表示函数的输出

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!("!?!?!"),
    }
}

【讨论】:

  • 这看起来很有希望,我会玩一下!随着函数签名列表的增加,它可能会变得有点负担,但如果没有可变参数的概念,我们可能会受到限制。
【解决方案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
}

【讨论】:

    猜你喜欢
    • 2018-03-07
    • 1970-01-01
    • 2018-08-19
    • 2013-04-10
    • 2018-11-11
    • 2020-04-29
    • 2013-03-16
    • 2014-10-29
    相关资源
    最近更新 更多