如何防止值被移动?
How to prevent a value from being moved?
我在尝试解决 the robot simulator Exercism exercise 时遇到了很多乐趣,但我面临着一个价值转移问题,我似乎无法想出一个优雅的解决方案:
impl Robot {
pub fn new(x: isize, y: isize, d: Direction) -> Self {
Robot { position: Coordinate { x: x, y: y }, direction: d }
}
pub fn turn_right(mut self) -> Self {
match self.direction {
// ...
};
self
}
pub fn turn_left(mut self) -> Self {
match self.direction {
// ...
};
self
}
pub fn advance(mut self) -> Self {
match self.direction {
// ...
};
self
}
pub fn instructions(self, instructions: &str) -> Self {
for instruction in instructions.chars() {
match instruction {
'A' => { self.advance(); },
'R' => { self.turn_right(); },
'L' => { self.turn_left(); },
_ => {
println!("{} is not a valid instruction", instruction);
},
};
}
self
}
我收到此错误:
enter code hereerror[E0382]: use of moved value: `self`
--> src/lib.rs:60:26
|
60 | 'A' => { self.advance(); },
| ^^^^ value moved here in previous iteration of loop
|
= note: move occurs because `self` has type `Robot`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `self`
--> src/lib.rs:61:26
|
60 | 'A' => { self.advance(); },
| ---- value moved here
61 | 'R' => { self.turn_right(); },
| ^^^^ value used here after move
|
= note: move occurs because `self` has type `Robot`, which does not implement the `Copy` trait
我想我收到错误是因为 advance()
returns self
,但我不明白为什么值在块内使用时仍然移动。我真的必须实施 Copy
还是我错过了一个终生用例?
I think I get the error because advance() returns self ?
不,您收到该错误是因为 advance
消耗 self
(您的其他方法也会消耗)。
您的问题的惯用解决方案几乎肯定是让您的方法对 self
采用可变引用 (&mut
),而不是按值采用 self
。例如。签名 pub fn turn_right(mut self) -> Self
将变为 pub fn turn_right(&mut self)
(请注意,后者不会 return 任何东西)。您可以通过引用操纵机器人的状态,您的 instructions
函数应该可以正常工作。
如果出于某种原因您希望继续让方法按值获取 self
,您可以重写 instructions
如下:
pub fn instructions(self, instructions: &str) -> Self {
let mut robot = self;
for instruction in instructions.chars() {
robot = match instruction {
'A' => { robot.advance() },
'R' => { robot.turn_right() },
'L' => { robot.turn_left() },
_ => {
println!("{} is not a valid instruction", instruction);
robot
},
};
}
robot
}
即继续按值传递机器人的状态,但要确保新状态在每次循环迭代时都绑定到一个变量。
(我没试过编译这段代码,但原理应该是合理的。)
看看其他用户的回答,其实你可以用 fold 来做:
pub fn instructions(self, instructions: &str) -> Self {
instructions.chars().fold(self, |robot, c| {
match c {
'L' => robot.turn_left(),
'R' => robot.turn_right(),
'A' => robot.advance(),
_ => panic!("unexpected char")
}
})
}
似乎一直在向后移动机器人进入范围。
我在尝试解决 the robot simulator Exercism exercise 时遇到了很多乐趣,但我面临着一个价值转移问题,我似乎无法想出一个优雅的解决方案:
impl Robot {
pub fn new(x: isize, y: isize, d: Direction) -> Self {
Robot { position: Coordinate { x: x, y: y }, direction: d }
}
pub fn turn_right(mut self) -> Self {
match self.direction {
// ...
};
self
}
pub fn turn_left(mut self) -> Self {
match self.direction {
// ...
};
self
}
pub fn advance(mut self) -> Self {
match self.direction {
// ...
};
self
}
pub fn instructions(self, instructions: &str) -> Self {
for instruction in instructions.chars() {
match instruction {
'A' => { self.advance(); },
'R' => { self.turn_right(); },
'L' => { self.turn_left(); },
_ => {
println!("{} is not a valid instruction", instruction);
},
};
}
self
}
我收到此错误:
enter code hereerror[E0382]: use of moved value: `self`
--> src/lib.rs:60:26
|
60 | 'A' => { self.advance(); },
| ^^^^ value moved here in previous iteration of loop
|
= note: move occurs because `self` has type `Robot`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `self`
--> src/lib.rs:61:26
|
60 | 'A' => { self.advance(); },
| ---- value moved here
61 | 'R' => { self.turn_right(); },
| ^^^^ value used here after move
|
= note: move occurs because `self` has type `Robot`, which does not implement the `Copy` trait
我想我收到错误是因为 advance()
returns self
,但我不明白为什么值在块内使用时仍然移动。我真的必须实施 Copy
还是我错过了一个终生用例?
I think I get the error because advance() returns self ?
不,您收到该错误是因为 advance
消耗 self
(您的其他方法也会消耗)。
您的问题的惯用解决方案几乎肯定是让您的方法对 self
采用可变引用 (&mut
),而不是按值采用 self
。例如。签名 pub fn turn_right(mut self) -> Self
将变为 pub fn turn_right(&mut self)
(请注意,后者不会 return 任何东西)。您可以通过引用操纵机器人的状态,您的 instructions
函数应该可以正常工作。
如果出于某种原因您希望继续让方法按值获取 self
,您可以重写 instructions
如下:
pub fn instructions(self, instructions: &str) -> Self {
let mut robot = self;
for instruction in instructions.chars() {
robot = match instruction {
'A' => { robot.advance() },
'R' => { robot.turn_right() },
'L' => { robot.turn_left() },
_ => {
println!("{} is not a valid instruction", instruction);
robot
},
};
}
robot
}
即继续按值传递机器人的状态,但要确保新状态在每次循环迭代时都绑定到一个变量。 (我没试过编译这段代码,但原理应该是合理的。)
看看其他用户的回答,其实你可以用 fold 来做:
pub fn instructions(self, instructions: &str) -> Self {
instructions.chars().fold(self, |robot, c| {
match c {
'L' => robot.turn_left(),
'R' => robot.turn_right(),
'A' => robot.advance(),
_ => panic!("unexpected char")
}
})
}
似乎一直在向后移动机器人进入范围。