Rust 如何分配到匹配分支内的匹配表达式中使用的变量?
我正在尝试实现一个通用函数Rust 如何分配到匹配分支内的匹配表达式中使用的变量?,rust,match,lifetime,borrow-checker,Rust,Match,Lifetime,Borrow Checker,我正在尝试实现一个通用函数join(),它可以在迭代器的任何迭代器上工作。我在next()方法实现中的match表达式中遇到借用检查器问题。以下是我的代码的简化版本: pub struct Join<I> where I: Iterator, I::Item: IntoIterator, { outer_iter: I, inner_iter: Option<<I::Item as IntoIterator>::IntoIter>
join()
,它可以在迭代器的任何迭代器上工作。我在next()
方法实现中的match
表达式中遇到借用检查器问题。以下是我的代码的简化版本:
pub struct Join<I>
where
I: Iterator,
I::Item: IntoIterator,
{
outer_iter: I,
inner_iter: Option<<I::Item as IntoIterator>::IntoIter>,
}
impl<I> Join<I>
where
I: Iterator,
I::Item: IntoIterator,
{
pub fn new(mut iter: I) -> Join<I> {
let inner_iter = iter.next().map(|it| it.into_iter());
Join {
outer_iter: iter,
inner_iter,
}
}
}
impl<I> Iterator for Join<I>
where
I: Iterator,
I::Item: IntoIterator,
{
type Item = <I::Item as IntoIterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
loop {
match &mut self.inner_iter {
Some(ref mut it) => match it.next() {
Some(x) => {
return Some(x);
}
None => {
self.inner_iter = self.outer_iter.next().map(|it| it.into_iter());
}
},
None => {
return None;
}
}
}
}
}
pub trait MyItertools: Iterator {
fn join(self) -> Join<Self>
where
Self: Sized,
Self::Item: IntoIterator,
{
Join::new(self)
}
}
impl<I> MyItertools for I where I: Iterator {}
#[cfg(test)]
mod test {
use super::MyItertools;
#[test]
fn it_works() {
let input = [[1], [2]];
let expected = [&1, &2];
assert_eq!(input.iter().join().collect::<Vec<_>>(), expected);
}
}
我理解为什么借用检查器抱怨我的代码,但我没有找到一个好的解决方案,只有一个丑陋的解决方法:
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.inner_iter.take() {
Some(mut it) => {
match it.next() {
Some(x) => { self.inner_iter = Some(it); return Some(x); }
None => { self.inner_iter = self.outer_iter.next().map(|it| it.into_iter()); }
}
}
None => { return None; }
}
}
}
fn下一步(&mut self)->选项{
环路{
匹配self.inner_iter.take(){
一些(mut it)=>{
匹配它。下一个(){
Some(x)=>{self.inner_iter=Some(it);返回Some(x);}
None=>{self.inner_iter=self.outer_iter.next().map(| it | it.into_iter());}
}
}
None=>{返回None;}
}
}
}
我想象这样的情况经常发生;如何重写代码来处理或避免它们?在这种情况下,我发现将代码分为两部分很有用:首先收集数据,然后更新可变数据:
fn next(&mut self) -> Option<Self::Item> {
loop {
//collect the change into a local variable
let ii = match &mut self.inner_iter {
Some(ref mut it) => {
match it.next() {
Some(x) => { return Some(x); }
None => self.outer_iter.next().map(|it| it.into_iter())
}
}
None => { return None; }
};
//self.inner_iter is no longer borrowed, update
self.inner_iter = ii;
}
}
fn下一步(&mut self)->选项{
环路{
//将更改收集到局部变量中
设ii=匹配和多个内部{
一些(参考mut it)=>{
匹配它。下一个(){
Some(x)=>{返回Some(x);}
None=>self.outer_iter.next().map(| it | it.into_iter())
}
}
None=>{返回None;}
};
//self.internal_iter不再被借用,请更新
自内电阻=ii;
}
}
事实上,所有不修改
内部代码的分支都执行返回
,这使得代码变得更容易。在这种情况下,我发现将代码分为两部分很有用:首先收集数据,然后更新可变数据:
fn next(&mut self) -> Option<Self::Item> {
loop {
//collect the change into a local variable
let ii = match &mut self.inner_iter {
Some(ref mut it) => {
match it.next() {
Some(x) => { return Some(x); }
None => self.outer_iter.next().map(|it| it.into_iter())
}
}
None => { return None; }
};
//self.inner_iter is no longer borrowed, update
self.inner_iter = ii;
}
}
fn下一步(&mut self)->选项{
环路{
//将更改收集到局部变量中
设ii=匹配和多个内部{
一些(参考mut it)=>{
匹配它。下一个(){
Some(x)=>{返回Some(x);}
None=>self.outer_iter.next().map(| it | it.into_iter())
}
}
None=>{返回None;}
};
//self.internal_iter不再被借用,请更新
自内电阻=ii;
}
}
事实上,所有不修改内部代码的分支都执行返回,这使得代码变得更容易。下面是问题的简单再现:
fn main() {
let mut a = (42, true);
match a {
(ref _i, true) => a = (99, false),
(ref _i, false) => a = (42, true),
}
println!("{:?}", a);
}
错误[E0506]:无法分配给'a',因为它是借用的
-->src/main.rs:4:27
|
4 |(参考i,真)=>a=(99,假),
|----^^^^^^^^^^^^此处发生借来的'a'的赋值
| |
|a的借词出现在这里
错误[E0506]:无法分配给'a',因为它是借用的
-->src/main.rs:5:28
|
5 |(参考i,假)=>a=(42,真),
|----^^^^^^^^^^^此处发生借来的'a'的赋值
| |
|a的借词出现在这里
这是基于AST的借用检查器的一个弱点。启用时,此选项将被禁用。增强的基于MIR的借用检查器可以看到,在尝试替换匹配的on变量时,该变量没有借用
无论如何,您的加入
只是一个:
或:
您可以看到这些是如何用于另一个想法的:
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(v) = self.inner_iter.as_mut().and_then(|i| i.next()) {
return Some(v);
}
match self.outer_iter.next() {
Some(x) => self.inner_iter = Some(x.into_iter()),
None => return None,
}
}
}
下面是问题的简单再现:
fn main() {
let mut a = (42, true);
match a {
(ref _i, true) => a = (99, false),
(ref _i, false) => a = (42, true),
}
println!("{:?}", a);
}
错误[E0506]:无法分配给'a',因为它是借用的
-->src/main.rs:4:27
|
4 |(参考i,真)=>a=(99,假),
|----^^^^^^^^^^^^此处发生借来的'a'的赋值
| |
|a的借词出现在这里
错误[E0506]:无法分配给'a',因为它是借用的
-->src/main.rs:5:28
|
5 |(参考i,假)=>a=(42,真),
|----^^^^^^^^^^^此处发生借来的'a'的赋值
| |
|a的借词出现在这里
这是基于AST的借用检查器的一个弱点。启用时,此选项将被禁用。增强的基于MIR的借用检查器可以看到,在尝试替换匹配的on变量时,该变量没有借用
无论如何,您的加入
只是一个:
或:
您可以看到这些是如何用于另一个想法的:
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(v) = self.inner_iter.as_mut().and_then(|i| i.next()) {
return Some(v);
}
match self.outer_iter.next() {
Some(x) => self.inner_iter = Some(x.into_iter()),
None => return None,
}
}
}
您也可以这样做:self.inner\u iter=match&mut self.inner\u iter{…}代码>。从匹配表达式中提取赋值是满足借用检查器要求的。在这种情况下,是否使用局部变量仅仅关系到可读性。您还可以这样做:self.inner\u iter=match&mut self.inner\u iter{…}代码>。从匹配表达式中提取赋值是满足借用检查器要求的。在这种情况下,是否使用局部变量仅仅关系到可读性。