在`match`分支内部借用可变变量。

huangapple go评论54阅读模式
英文:

Borrow mutable inside of `match` arm

问题

I'm new to Rust, so I'm sorry if this question has an absolutely obvious solution. I cannot find cleaner way to write the code below. I know this code cause panic because of container is already borrowed.

问题是在匹配 parent 时,阻止我更改 container 属性。由于匹配 parent 并更改 active 状态,这两者在我的代码中是独立的,所以我认为这段代码是安全的。

我也知道可以通过将可变引用移出 match 并将 match 更改为 if let 来解决这个问题,如下所示。变量 active 在开始时设置为 true

是否有更可读更清晰的方式来编写具有相同功能的代码?

如果解决这个问题很重要,整个代码实现了具有容器内部小部件的节点,其中容器必须知道其父级。

函数声明:

pub fn move_focus(
  container: &Rc<RefCell<Container>>,
  direction: Direction,
  f: fn(&RcCon) -> Option<Rc<RefCell<Container>>>,
) -> Rc<RefCell<Container>>

结构体:

pub struct Container {
    pub items: Vec<Item>,
    pub layout: Layout,
    pub direction: Direction,
    pub parent: Option<Rc<RefCell<Container>>,
    pub act_index: usize,
    pub active: bool,
}

pub enum Item {
    Container(RcCon),
    Widget(Holder),
}
英文:

I'm new to Rust, so I'm sorry if this question has an absolutely obvious solution. I cannot find cleaner way to write the code below. I know this code cause panic because of container is already borrowed.

return match &amp;container.borrow().parent {
  Some(parent) =&gt; {
    container.borrow_mut().active = false;
    Layout::move_focus(parent, direction, f)
  }
  None =&gt; Rc::clone(container),
}

Problem there is preventing me from changing a container attributes while I'm matching parent. Because of matching parent and changing active state, that are independent in my code, I think this code is safe.

I also know this can be solved by moving mutable borrow out of match and changing match to if let as is shown in the code below. Variable active is set to true at the beginning.

{
  container.borrow_mut().active = false;
}
if let Some(parent) = &amp;container.borrow().parent {
  return Layout::move_focus(parent, direction, f);
}
container.borrow_mut().active = true;
Rc::clone(container)

Is there a more readable and cleaner way to write code with the same functionality?

If it is important for solving this problem the whole code implements nodes that have containers on widgets inside, where containers must know their parents.

Function declaration:

pub fn move_focus(
  container: &amp;Rc&lt;RefCell&lt;Container&gt;&gt;,
  direction: Direction,
  f: fn(&amp;RcCon) -&gt; Option&lt;Rc&lt;RefCell&lt;Container&gt;&gt;&gt;,
) -&gt; Rc&lt;RefCell&lt;Container&gt;&gt;

Structs:

pub struct Container {
    pub items: Vec&lt;Item&gt;,
    pub layout: Layout,
    pub direction: Direction,
    pub parent: Option&lt;Rc&lt;RefCell&lt;Container&gt;&gt;,
    pub act_index: usize,
    pub active: bool,
}

pub enum Item {
    Container(RcCon),
    Widget(Holder),
}

答案1

得分: 1

你可以首先将整个容器作为 mut 借用,然后对其进行操作。

let mut c = container.borrow_mut();

return match c.parent {
  Some(parent) => {
    c.active = false;
    Layout::move_focus(parent, direction, f)
  }
  None => Rc::clone(container),
}

另外,将 &amp;Rc 作为参数传递不符合 Rust 的惯用方式。建议直接传递 Rc

英文:

You can borrow whole container as mut firstly, and then do operations on it.

let mut c = container.borrow_mut();

return match c.parent {
  Some(parent) =&gt; {
    c.active = false;
    Layout::move_focus(parent, direction, f)
  }
  None =&gt; Rc::clone(container),
}

Also passing &amp;Rc as an argument is not idiomatic rust. Prefer passing Rc directly.

huangapple
  • 本文由 发表于 2023年5月21日 00:15:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76296168.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定