Functional programming “我能摆脱”吗;mut";在这里

Functional programming “我能摆脱”吗;mut";在这里,functional-programming,rust,Functional Programming,Rust,我有一个字符串向量,我想从中提取一些数据,并从中创建一个结构。它看起来像这样: let mut my_struct = MyStruct::new(0, 0, 0); let regex1 = Regex::new("..."); let regex2 = Regex::new("..."); for s_iter in my_str_vec.iter() { if regex1.is_match(s_iter) { // parsing the value

我有一个字符串向量,我想从中提取一些数据,并从中创建一个结构。它看起来像这样:

let mut my_struct = MyStruct::new(0, 0, 0);
let regex1 = Regex::new("...");
let regex2 = Regex::new("...");

for s_iter in my_str_vec.iter() {
    if regex1.is_match(s_iter) {
        // parsing the value
        // .........
        let var1 = regex1.captures("....");

        // and assign it to to a field of the struct instance
        my_struct.field1 = var1;
    }

    // do the same thing for other fields each step in the loop
    // each step only one regex gets triggered

    if regex2.is_match(s_iter) {
        // parsing the value
        // .........
        let var2 = regex12.captures("....");

        // and assign it to to a field of the struct instance
        my_struct.field2 = var2;
    }
}

// now "my_struct" is now completely initialized
fn parse(my_str_vec: Vec<&str>) -> MyStruct {
    let my_struct = MyStruct::new(0, 0, 0);
    let regex1 = Regex::new(...);
    let regex2 = Regex::new(...);

    fn process_next<I>(regex1: Regex, regex2: Regex, mut str_iter: I, my_struct: MyStruct) -> MyStruct
        where I: Iterator, I::Item: AsRef<str>
    {
        match str_iter.next() {
            Some(s_iter) => {
                let my_struct = if regex1.is_match(s_iter.as_ref()) {
                    let var1 = regex1.captures("var1");
                    MyStruct { field1: var1, ..my_struct }
                } else if regex2.is_match(s_iter.as_ref()) {
                    let var2 = regex2.captures("var2");
                    MyStruct { field2: var2, ..my_struct }
                } else {
                    my_struct
                };

                process_next(regex1, regex2, str_iter, my_struct)
            }
            None => my_struct
        }
    }

    process_next(regex1, regex2, my_str_vec.iter(), my_struct)
}

如您所见,我必须对结构使用
mut
。没有
mut
,有没有办法做到这一点?我希望能够一次初始化所有结构,而无需
mut
。或者我可以考虑其他的选择,而不是<代码> MUT也。

< P>在纯函数语言中,你需要定义一个递归函数。在Rust中,它看起来是这样的:

let mut my_struct = MyStruct::new(0, 0, 0);
let regex1 = Regex::new("...");
let regex2 = Regex::new("...");

for s_iter in my_str_vec.iter() {
    if regex1.is_match(s_iter) {
        // parsing the value
        // .........
        let var1 = regex1.captures("....");

        // and assign it to to a field of the struct instance
        my_struct.field1 = var1;
    }

    // do the same thing for other fields each step in the loop
    // each step only one regex gets triggered

    if regex2.is_match(s_iter) {
        // parsing the value
        // .........
        let var2 = regex12.captures("....");

        // and assign it to to a field of the struct instance
        my_struct.field2 = var2;
    }
}

// now "my_struct" is now completely initialized
fn parse(my_str_vec: Vec<&str>) -> MyStruct {
    let my_struct = MyStruct::new(0, 0, 0);
    let regex1 = Regex::new(...);
    let regex2 = Regex::new(...);

    fn process_next<I>(regex1: Regex, regex2: Regex, mut str_iter: I, my_struct: MyStruct) -> MyStruct
        where I: Iterator, I::Item: AsRef<str>
    {
        match str_iter.next() {
            Some(s_iter) => {
                let my_struct = if regex1.is_match(s_iter.as_ref()) {
                    let var1 = regex1.captures("var1");
                    MyStruct { field1: var1, ..my_struct }
                } else if regex2.is_match(s_iter.as_ref()) {
                    let var2 = regex2.captures("var2");
                    MyStruct { field2: var2, ..my_struct }
                } else {
                    my_struct
                };

                process_next(regex1, regex2, str_iter, my_struct)
            }
            None => my_struct
        }
    }

    process_next(regex1, regex2, my_str_vec.iter(), my_struct)
}
fn parse(my\u str\u vec:vec)->MyStruct{
让my_struct=MyStruct::new(0,0,0);
让regex1=Regex::new(…);
让regex2=Regex::new(…);
fn process_next(regex1:Regex,regex2:Regex,mut str_iter:I,my_struct:MyStruct)->MyStruct
其中I:Iterator,I::Item:AsRef
{
匹配str_iter.next(){
一些(s_iter)=>{
让my_struct=if regex1.is_匹配(s_iter.as_ref()){
设var1=regex1.captures(“var1”);
MyStruct{field1:var1,…my_struct}
}如果regex2.is_匹配(s_iter.as_ref()),则为else{
设var2=regex2.captures(“var2”);
MyStruct{field2:var2,…my_struct}
}否则{
我的结构
};
下一个进程(regex1、regex2、str\u iter、my\u struct)
}
无=>my_结构
}
}
下一个进程(regex1,regex2,my_str_vec.iter(),my_struct)
}
注意,在这个代码中仍然有一个
mut
:我们必须将
str_iter
定义为可变的,因为调用要求接收方是可变的


虽然内部函数是尾部递归的,但Rust不能保证尾部调用,因此如果输入太大,它可能会因堆栈溢出而崩溃。就我个人而言,我宁愿在这里使用
mut
,就像在您的原始代码中一样,特别是因为Rust中的
mut
意味着没有别名,这消除了一整类潜在的bug。

在纯函数式语言中,您需要定义一个递归函数。在Rust中,它看起来是这样的:

let mut my_struct = MyStruct::new(0, 0, 0);
let regex1 = Regex::new("...");
let regex2 = Regex::new("...");

for s_iter in my_str_vec.iter() {
    if regex1.is_match(s_iter) {
        // parsing the value
        // .........
        let var1 = regex1.captures("....");

        // and assign it to to a field of the struct instance
        my_struct.field1 = var1;
    }

    // do the same thing for other fields each step in the loop
    // each step only one regex gets triggered

    if regex2.is_match(s_iter) {
        // parsing the value
        // .........
        let var2 = regex12.captures("....");

        // and assign it to to a field of the struct instance
        my_struct.field2 = var2;
    }
}

// now "my_struct" is now completely initialized
fn parse(my_str_vec: Vec<&str>) -> MyStruct {
    let my_struct = MyStruct::new(0, 0, 0);
    let regex1 = Regex::new(...);
    let regex2 = Regex::new(...);

    fn process_next<I>(regex1: Regex, regex2: Regex, mut str_iter: I, my_struct: MyStruct) -> MyStruct
        where I: Iterator, I::Item: AsRef<str>
    {
        match str_iter.next() {
            Some(s_iter) => {
                let my_struct = if regex1.is_match(s_iter.as_ref()) {
                    let var1 = regex1.captures("var1");
                    MyStruct { field1: var1, ..my_struct }
                } else if regex2.is_match(s_iter.as_ref()) {
                    let var2 = regex2.captures("var2");
                    MyStruct { field2: var2, ..my_struct }
                } else {
                    my_struct
                };

                process_next(regex1, regex2, str_iter, my_struct)
            }
            None => my_struct
        }
    }

    process_next(regex1, regex2, my_str_vec.iter(), my_struct)
}
fn parse(my\u str\u vec:vec)->MyStruct{
让my_struct=MyStruct::new(0,0,0);
让regex1=Regex::new(…);
让regex2=Regex::new(…);
fn process_next(regex1:Regex,regex2:Regex,mut str_iter:I,my_struct:MyStruct)->MyStruct
其中I:Iterator,I::Item:AsRef
{
匹配str_iter.next(){
一些(s_iter)=>{
让my_struct=if regex1.is_匹配(s_iter.as_ref()){
设var1=regex1.captures(“var1”);
MyStruct{field1:var1,…my_struct}
}如果regex2.is_匹配(s_iter.as_ref()),则为else{
设var2=regex2.captures(“var2”);
MyStruct{field2:var2,…my_struct}
}否则{
我的结构
};
下一个进程(regex1、regex2、str\u iter、my\u struct)
}
无=>my_结构
}
}
下一个进程(regex1,regex2,my_str_vec.iter(),my_struct)
}
注意,在这个代码中仍然有一个
mut
:我们必须将
str_iter
定义为可变的,因为调用要求接收方是可变的


虽然内部函数是尾部递归的,但Rust不能保证尾部调用,因此如果输入太大,它可能会因堆栈溢出而崩溃。就我个人而言,我宁愿在这里使用
mut
,就像在您的原始代码中一样,特别是因为Rust中的
mut
意味着没有别名,这消除了一整类潜在的bug。

我相信您一定有理由这样问,但请注意,在Rust
mut
中,它并不是默认值,不应该在不必要时使用。通常情况下,使某些内容可变会使代码的其余部分变得更简单、更快,而这正是Rust鼓励的。我肯定你有理由这样问,但请注意,在Rust
mut
中,mut并不是真正不受欢迎的-它只是不是默认值,不应该在不必要时使用。通常情况下,使某些内容可变会使其余的代码更简单、更快,而这正是Rust所鼓励的。