当函数来自不同模块时,如何在 Rust 中实现函数向量(数组,..)

Sea*_*rry 1 arrays rust

我见过:

并在网上搜索。我不想关闭。我正在尝试实现一个经典的动态(-ish)函数查找表。

mod impl_foo;
mod impl_bar;

use utils;
// a CmdResult is a Result with a tuple of an int and a string

static FUNCTIONS: &'static [fn(&[String]) -> utils::CmdResult] = &[
    ("bar".to_string(), impl_bar::call_bar),
    ("foo".to_string(), impl_foo::call),
];

fn find_action(name: &String) -> (fn(&[String]) -> utils::CmdResult) {
    match FUNCTIONS.binary_search_by(|item| item[0].cmp(name)) {
        Ok(action) => action,
        Err(_) => (|&[String]| Err((1, format!("Unknown '{}'", name))))
    }
}

// later on in another function ....
Run Code Online (Sandbox Code Playgroud)

动作 = find_action("foo"); 让结果=动作(参数);// 处理结果

但这不能编译:

src/main.rs:44:5: 44:50 error: mismatched types:
   expected `fn(&[collections::string::String]) ->    core::result::Result<i32, (i32, collections::string::String)>`,
found `(collections::string::String, fn(&[collections::string::String]) -> core::result::Result<i32, (i32, collections::string::String)> {impl_foo::call})`
Run Code Online (Sandbox Code Playgroud)

再次为impl_bar::call_bar.

我缺少什么?它似乎与不同模块的使用有关,因为它显然适用于其他人。

我还尝试定义一个类型:

type Action = fn(&[String]) -> utils::CmdResult;
Run Code Online (Sandbox Code Playgroud)

并用它来减少打字,但也没有运气。

顺便说一句,你需要#![feature(slice_patterns)]因为&[String].

第二天早上编辑……

正如弗朗西斯在下面指出的那样,我的转录有一个缺陷。它与我遇到的实际问题并不完全相符,但它帮助我以新的眼光看待问题。切片模式要求是因为我试图用闭包处理未知函数。一旦我删除了该投诉就消失了。我认为我试图采用一种过于动态的语言风格:-)

下面是实际有效的完整代码,以便发现此问题的人可以看到工作代码。

type Action = fn(&[String]) -> utils::CmdResult;

static FUNCTIONS: &'static [(&'static str, Action)] = &[
    ("bar", impl_bar::call),
    ("foo", impl_foo::call_foo),
];

fn find_action(prog: &String) -> Option<Action> {
    match FUNCTIONS.binary_search_by(|&(name,_)| name.cmp(prog)) {
        Ok(idx) => Some(FUNCTIONS[idx].1),
        Err(_) => None,
    }
}

fn invoke(prog: &String, args: &[String]) -> i32 {
    let result = match find_action(prog) {
        Some(action) => action(args),
        None => Err((1, format!("Unknown: {}", prog))),
    };

    result.unwrap_or_else(|(n, msg)| {
        writeln!(io::stderr(), "{}", msg).ok();
        n
    })
}
Run Code Online (Sandbox Code Playgroud)

Fra*_*gné 5

仔细阅读错误信息:

src/main.rs:44:5: 44:50 error: mismatched types:
   expected `fn(&[collections::string::String]) ->    core::result::Result<i32, (i32, collections::string::String)>`,
found `(collections::string::String, fn(&[collections::string::String]) -> core::result::Result<i32, (i32, collections::string::String)> {impl_foo::call})`
Run Code Online (Sandbox Code Playgroud)

让我们简化一下:

src/main.rs:44:5: 44:50 error: mismatched types:
   expected `fn(&[String]) -> Result<i32, (i32, String)>`,
found `(String, fn(&[String]) -> Result<i32, (i32, String)> {impl_foo::call})`
Run Code Online (Sandbox Code Playgroud)

此消息告诉您的是,您正在尝试将元组String和函数类型放入仅需要函数类型的数组中。

您可能想像这样定义您的数组:

static FUNCTIONS: &'static [(&'static str, fn(&[String]) -> utils::CmdResult]) = &[
    ("bar", impl_bar::call_bar),
    ("foo", impl_foo::call),
];
Run Code Online (Sandbox Code Playgroud)