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