rust - 如何借用结构的 curry 函数字段?

标签 rust traits currying borrow-checker parser-combinators

我有一个带有字段的Parser结构,transformer用来保存函数。该函数返回一个闭包,该闭包处理一个ParserState并返回一个ParserState。我已经创建了一个函数str_parser,我将其用作Parser的新实例的转换器。

pub struct Parser<F> 
    where F: FnOnce(ParserState) -> ParserState {
    pub transformer: F
}

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

impl<F> Parser<F> 
    where F: FnOnce(ParserState) -> ParserState {
    pub fn new(f: F) -> Self {
        // creating a new Parser just means deciding on which closure it applies
        Parser {
            transformer: f,
        }
    }

    pub fn run(&self, corpus: String) -> ParserState {
        let state = ParserState {
            target: corpus,
            index: 0,
            result: None,
            error: false,
            err_msg: None
        };
        return (self.transformer)(state);
    }
}

pub fn str_parser(needle: String) -> impl FnOnce(ParserState) -> ParserState {
    let parser = move |state: ParserState| {
        let target_string = state.target;
        let index = state.index;
        if target_string[index..needle.len()] == needle {
            ParserState {
                target: target_string,
                index: index + needle.len(),
                result: Some(needle),
                error: false,
                err_msg: None
            }
        } else {
            ParserState {
                target: String::from(""),
                index: 0,
                result: None,
                error: true,
                err_msg: Some(String::from("Error"))
            }
        }
    };
    parser
}

由于出现此错误,借位检查器拒绝让我将此函数应用于提供的参数。

error[E0507]: cannot move out of `self.transformer` which is behind a shared reference
  --> src/parsers.rs:32:16
   |
32 |         return (self.transformer)(state);
   |                ^^^^^^^^^^^^^^^^^^ move occurs because `self.transformer` has type `F`, which does not implement the `Copy` trait


我该怎么办?在这种情况下,实现Copy特性对我来说似乎是艰巨的。有没有办法使这合法化,同时仍然允许我 curry 这个str_parser函数?

最佳答案

在这种情况下,我有一个Parser,除了transformer之外没有任何状态。因此,我不需要使用FnOnceFn是我所需要的。从那里,我修改了str_parser函数中使用的闭包以克隆needle字符串:

pub struct Parser<F> 
    where F: Fn(ParserState) -> ParserState {
    pub transformer: F
}

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

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,
        }
    }

    pub fn run(&self, corpus: String) -> ParserState {
        let state = ParserState {
            target: corpus,
            index: 0,
            result: None,
            error: false,
            err_msg: None
        };
        return (self.transformer)(state);
    }
}

pub fn str_parser(needle: String) -> impl Fn(ParserState) -> ParserState {
    move |mut state: ParserState| {
        let target_string = state.target;
        let index = state.index;
        if target_string[index..needle.len()] == needle {
            state = ParserState {
                target: target_string,
                index: index + needle.len(),
                result: Some(needle.clone()),
                error: false,
                err_msg: None
            }
        } else {
            state = ParserState {
                target: String::from(""),
                index: 0,
                result: None,
                error: true,
                err_msg: Some(String::from("Error"))
            }
        }
        state
    }
}

关于rust - 如何借用结构的 curry 函数字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61370368/

相关文章:

rust - 为什么编译器告诉我考虑使用 `let` 绑定(bind)?

rust - 未使用 termion 恢复终端状态

rust - 无法使用对实现特征的类型的引用来调用函数

functional-programming - 这被认为是 curry 函数吗?

list - 在 Lisp 中柯里化(Currying) : difference between (list 1 2 3) and (1 2 3)?

javascript - 使用 valueOf 数学运算进行类型强制

generics - 返回通用结构的函数的签名是什么?

rust - 是否可以在 Rust 中使用 SIMD 指令?

data-structures - 如何在特征的函数中发送不同的结构?

c++ - 按特征类专门化功能