我正在对Rust书中的dining philosophers问题进行一些修改。
在书中,他们手动创造了所有的哲学家,最后一个人用左手和右手切换。我以编程方式完成了这项工作(使用我推动哲学家推进的for循环),现在我想修改最终的哲学家。
这就是我想要做的事情
// make the last philosopher left handed (switch forks)
let p = &philosophers[length - 1];
philosophers[length - 1] = Philosopher{left: p.right, right: p.left, name: p.name.clone()};
// error: cannot move out of indexed content [E0507]
这就是我必须要做的事情
philosophers[length - 1] = Philosopher{
left: philosophers[length - 1].right,
right: philosophers[length - 1].left,
name: philosophers[length -1].name.clone(),
};
第一个例子没有编译,我无法找到一种方法来编译它而不需要像let p = philosophers[length - 1].clone()
那样完全复制数据! (不是我想要的)。
有没有办法更加鲁莽地做到这一点?
答案 0 :(得分:3)
事实上,你无法改变你正在借用的东西。您可以克隆它 - 您已经克隆了name
字段,而left
和right
仅为usize
。
假设您的结构包含更多更大的数据,克隆不是一种选择。在这种情况下,有多种可能的解决方案。您可以使用Vec
而不是普通数组:首先创建所有4个普通哲学家,然后创建最后一个push
。或者您可以使用std::mem::swap
来交换left
和right
:
std::mem::swap(&mut philosophers[length - 1].left, &mut philosophers[length - 1].right);
答案 1 :(得分:0)
这个例子很短,以至于恕我直言的原始解决方案(没有循环)更具表现力。但如果你想改变最后一位哲学家,你可以这样做:
let p = &mut philosophers[length - 1];
let left = p.left;
let right = p.right;
p.left = right;
p.right = left;
您将直接操作最后一位哲学家的参考。这样,您不需要克隆他/她的名字,只需交换fork ID。