不能借用 <var> 作为不可变的,因为它也被借用为可变的不可变借用发生在这里
cannot borrow <var> as immutable because it is also borrowed as mutable immutable borrow occurs here
学习一些 Rust 编程(Leetcode Q3)。
收到错误:
cannot borrow `result` as immutable because it is also borrowed as mutable
immutable borrow occurs hererustcE0502
solution.rs(42, 23): mutable borrow occurs here
solution.rs(44, 13): mutable borrow later used here
我可以将程序从 if result.is_none() {
更改为 if current.is_none() {
,它会起作用。但是当前和结果不是一回事。当前是 linked 列表中的最后一个节点,结果是头。我该怎么做?
Rust 游乐场link:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=741c07fad8aa730a44ba5773395aed7c
// Definition for singly-linked list.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>
}
impl ListNode {
#[inline]
fn new(val: i32) -> Self {
ListNode {
next: None,
val
}
}
}
#[allow(dead_code)]
struct Solution;
#[allow(dead_code)]
impl Solution {
pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let mut carry = 0;
let mut result: Option<Box<ListNode>> = None;
let mut current: &mut Option<Box<ListNode>> = &mut None;
let mut node1 = &l1;
let mut node2 = &l2;
while node1.is_some() || node2.is_some() || carry > 0 {
if node1.is_some() {
carry += node1.as_ref().unwrap().val;
node1 = &node1.as_ref().unwrap().next;
}
if node2.is_some() {
carry += node2.as_ref().unwrap().val;
node2 = &node2.as_ref().unwrap().next;
}
if result.is_none() { // solution.rs(42, 23): mutable borrow occurs here
result = Some(Box::new(ListNode::new(carry % 10)));
current = &mut result; // solution.rs(44, 13): mutable borrow later used here
} else {
current.as_mut().unwrap().next = Some(Box::new(ListNode::new(carry % 10)));
current = &mut current.as_mut().unwrap().next;
}
carry = carry / 10;
}
return result;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
fn from_vec(l: Vec<i32>) -> Option<Box<ListNode>> {
let mut start = None;
let mut current: &mut Option<Box<ListNode>> = &mut None;
for x in l {
if current.is_none() {
start = Some(Box::new(ListNode::new(x)));
current = &mut start;
} else {
current.as_mut().unwrap().next = Some(Box::new(ListNode::new(x)));
current = &mut current.as_mut().unwrap().next;
}
}
return start;
}
fn compute(l1: Vec<i32>, l2: Vec<i32>) -> Vec<i32> {
let result = Solution::add_two_numbers(from_vec(l1), from_vec(l2));
let mut node = &result;
let mut result_vec = Vec::new();
while node.is_some() {
result_vec.push(node.as_ref().unwrap().val);
node = &node.as_ref().unwrap().next;
}
return result_vec;
}
assert_eq!(compute(vec![2, 4, 3], vec![5, 6, 4]), vec![7, 0, 8]);
assert_eq!(compute(vec![0], vec![0]), vec![0]);
assert_eq!(compute(vec![9, 9, 9, 9, 9, 9, 9], vec![9, 9, 9, 9]), vec![8, 9, 9, 9, 0, 0, 0, 1]);
}
}
众所周知,由于这些别名问题,链表很难在 Rust 中实现。根本问题是你不能对 result
拥有的东西进行可变引用(即使是间接引用),然后在该引用处于活动状态时再次使用 result
。
问题的症结在于您检查 result
是否有值——换句话说,检查结果列表是否为空。这不起作用,因为在循环的第二次迭代中,current
引用 result
,因此 result
无法访问,因为它已被完全借用。
解决此问题的最简单方法是通过更改 current
点的位置来取消对 result.is_some()
的检查。
不是引用列表中可能存在也可能不存在的最后一个节点,而是引用下一个要填充的节点——即,末尾的 None
-- 总是 存在于 某处。
let mut result: Option<Box<ListNode>> = None;
let mut current: &mut Option<Box<ListNode>> = &mut result;
现在您不需要检查 result
因为 current
总是 指向您应该放置下一个节点的位置。这可能在 result
或节点的 next
字段中,但您不必关心它。
您可以将 if
/else
块替换为:
*current = Some(Box::new(ListNode::new(carry % 10)));
current = &mut current.as_mut().unwrap().next;
这是有效的,因为在它的声明和你从函数中 return 它的那一刻你没有访问 result
。当你 return 它时,current
引用不再被认为是活动的,因为 non-lexical lifetimes.
学习一些 Rust 编程(Leetcode Q3)。
收到错误:
cannot borrow `result` as immutable because it is also borrowed as mutable
immutable borrow occurs hererustcE0502
solution.rs(42, 23): mutable borrow occurs here
solution.rs(44, 13): mutable borrow later used here
我可以将程序从 if result.is_none() {
更改为 if current.is_none() {
,它会起作用。但是当前和结果不是一回事。当前是 linked 列表中的最后一个节点,结果是头。我该怎么做?
Rust 游乐场link:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=741c07fad8aa730a44ba5773395aed7c
// Definition for singly-linked list.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>
}
impl ListNode {
#[inline]
fn new(val: i32) -> Self {
ListNode {
next: None,
val
}
}
}
#[allow(dead_code)]
struct Solution;
#[allow(dead_code)]
impl Solution {
pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let mut carry = 0;
let mut result: Option<Box<ListNode>> = None;
let mut current: &mut Option<Box<ListNode>> = &mut None;
let mut node1 = &l1;
let mut node2 = &l2;
while node1.is_some() || node2.is_some() || carry > 0 {
if node1.is_some() {
carry += node1.as_ref().unwrap().val;
node1 = &node1.as_ref().unwrap().next;
}
if node2.is_some() {
carry += node2.as_ref().unwrap().val;
node2 = &node2.as_ref().unwrap().next;
}
if result.is_none() { // solution.rs(42, 23): mutable borrow occurs here
result = Some(Box::new(ListNode::new(carry % 10)));
current = &mut result; // solution.rs(44, 13): mutable borrow later used here
} else {
current.as_mut().unwrap().next = Some(Box::new(ListNode::new(carry % 10)));
current = &mut current.as_mut().unwrap().next;
}
carry = carry / 10;
}
return result;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
fn from_vec(l: Vec<i32>) -> Option<Box<ListNode>> {
let mut start = None;
let mut current: &mut Option<Box<ListNode>> = &mut None;
for x in l {
if current.is_none() {
start = Some(Box::new(ListNode::new(x)));
current = &mut start;
} else {
current.as_mut().unwrap().next = Some(Box::new(ListNode::new(x)));
current = &mut current.as_mut().unwrap().next;
}
}
return start;
}
fn compute(l1: Vec<i32>, l2: Vec<i32>) -> Vec<i32> {
let result = Solution::add_two_numbers(from_vec(l1), from_vec(l2));
let mut node = &result;
let mut result_vec = Vec::new();
while node.is_some() {
result_vec.push(node.as_ref().unwrap().val);
node = &node.as_ref().unwrap().next;
}
return result_vec;
}
assert_eq!(compute(vec![2, 4, 3], vec![5, 6, 4]), vec![7, 0, 8]);
assert_eq!(compute(vec![0], vec![0]), vec![0]);
assert_eq!(compute(vec![9, 9, 9, 9, 9, 9, 9], vec![9, 9, 9, 9]), vec![8, 9, 9, 9, 0, 0, 0, 1]);
}
}
众所周知,由于这些别名问题,链表很难在 Rust 中实现。根本问题是你不能对 result
拥有的东西进行可变引用(即使是间接引用),然后在该引用处于活动状态时再次使用 result
。
问题的症结在于您检查 result
是否有值——换句话说,检查结果列表是否为空。这不起作用,因为在循环的第二次迭代中,current
引用 result
,因此 result
无法访问,因为它已被完全借用。
解决此问题的最简单方法是通过更改 current
点的位置来取消对 result.is_some()
的检查。
不是引用列表中可能存在也可能不存在的最后一个节点,而是引用下一个要填充的节点——即,末尾的 None
-- 总是 存在于 某处。
let mut result: Option<Box<ListNode>> = None;
let mut current: &mut Option<Box<ListNode>> = &mut result;
现在您不需要检查 result
因为 current
总是 指向您应该放置下一个节点的位置。这可能在 result
或节点的 next
字段中,但您不必关心它。
您可以将 if
/else
块替换为:
*current = Some(Box::new(ListNode::new(carry % 10)));
current = &mut current.as_mut().unwrap().next;
这是有效的,因为在它的声明和你从函数中 return 它的那一刻你没有访问 result
。当你 return 它时,current
引用不再被认为是活动的,因为 non-lexical lifetimes.