包含闭包参数的方法期望错误的类型?

时间:2020-04-27 08:24:23

标签: generics rust closures

我有一个结构Parser,其中包含一个transformer-一个用于修改其ParserState-和所说的ParserState的函数。

#[derive(Clone)]
pub struct Parser<F> 
where
    F: Fn(ParserState) -> ParserState
{
    pub transformer: F,
    pub state: ParserState
}

#[derive(Debug, PartialEq, Clone)]
pub struct ParserState {
    pub target: String,
    pub index: usize,
    pub result: Vec<String>, // the container of eventual results from the parsing, with Some(result) or None. Should be a vetor
    pub error: bool,            // whether we've encountered an error; index -> 0, Some(err_msg)
    pub err_msg: Option<String> // Eventual error message
}

定义一个.map()方法时,我假设我可以简单地使用闭包,并在将解析器自身的状态作为传递给该闭包的参数时引用其自身的状态。该闭包将用作.map()方法的参数。

impl<F> Parser<F>
where
    F: Fn(ParserState) -> ParserState 
{
    pub fn new(f: F) -> Self {
        // creating a new Parser just means deciding on which closure it applies
        Parser {
            transformer: f,
            state: ParserState {
                target: String::from(""),
                index: 0,
                result: vec![],
                error: false,
                err_msg: None
            }
        }
    }

    pub fn map<G>(&mut self, g: G) -> ()
    where
        G: Fn(ParserState) -> ParserState
    {
        self.state = g((self.state).clone())
    }

    pub fn run(mut self, corpus: String) -> Self {
        self.state.target = corpus;
        self.state = (self.transformer)(self.state);
        self
    }
}

我正在这样使用它:

fn main() {
    let haystack: String = String::from("Hello!Goodbye!");
    let needle = String::from("Hello!");
    let str_parser = Parser::new(str_parser(needle));
    let closure = |mut state: ParserState| state.index = 0;
    let result = str_parser.run(haystack);
    let result = result.map(closure);
    let adv = ParserState {
        target: "Hello!Goodbye!".to_string(),
        index: 0,
        result: vec!["Hello!".to_string()],
        error: false,
        err_msg: None
    };
    assert_eq!(adv, result.state);
}

这没有用。我遇到此错误:

error[E0271]: type mismatch resolving `<[closure@src/lib.rs:49:23: 49:63] as std::ops::FnOnce<(parse
rs::ParserState,)>>::Output == parsers::ParserState`
  --> src/lib.rs:51:29
   |
51 |         let result = result.map(closure);
   |                             ^^^ expected `()`, found struct `parsers::ParserState`

并且不确定FnOnce(我没有提到)与之相关。当.map()()的方法时,我也不明白Parser期望"""<?xml version="1.0" encoding="utf-8"?> <pages> <page> <textbox> <new_line> <text size="12.482">C</text> <text size="12.333">A</text> <text size="12.333">P</text> <text size="12.333">I</text> <text size="12.482">T</text> <text size="12.482">O</text> <text size="12.482">L</text> <text size="12.482">O</text> <text></text> <text size="12.482">I</text> <text size="12.482">I</text> <text size="12.482">I</text> <text></text> </new_line> </textbox> </page> </pages> """ 作为参数。我在这里感觉有点不合时宜。

这里是the relevant Rust playground

的链接

1 个答案:

答案 0 :(得分:2)

此闭包返回()(即不返回值):

let closure = |mut state: ParserState| state.index = 0;

但是声明F返回一个ParserState。您只需要使函数按预期返回值即可。

let closure = |mut state: ParserState| {
    state.index = 0;
    state
};

并且不确定FnOnce的相关性,我没有提到。

FnOnce是最一般的功能特征;所有函数至少可以调用一次,因此所有函数都实现FnOnce,但可能不实现FnFnMut。我认为它在错误消息中提到FnOnce的事实只是它尝试匹配类型的顺序的伪像。