简体   繁体   English

在传递给该 object 的方法的闭包内使用 object

[英]use an object inside a closure which is passed to a method of that object

i have a struct Screen with its implementation我有一个结构屏幕及其实现

pub struct Screen {
    stdin:  Stdin,
// types are irrelevant
    stdout: MouseStdout,
}

impl Screen {
   // ...
    pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
        &self,
        mut handler: F,
    ) {
        let stdin = stdin();
        for e in stdin.events() {
            let e = e.unwrap();
            match e {
                Event::Key(Key::Ctrl('c')) => break,
                _ => {
                    handler(&e);
                },
            }

        }
    }
}

and usage (which is wrong and know it)和用法(这是错误的并且知道)

    let mut screen = Screen::new();
    screen.init_screen();

    screen.handle_keys_loop(|event| {
        match event {
            Event::Key(Key::Char('a')) => {
                screen.println("hello there",15, 1, true);
            },
            _ => {}
        }
    });

    screen.end_screen();

the error is错误是

error[E0502]: cannot borrow `screen` as mutable because it is also borrowed as immutable
  --> src/bin/terminal.rs:74:29
   |
74 |       screen.handle_keys_loop(|event| {
   |       -      ---------------- ^^^^^^^ mutable borrow occurs here
   |       |      |
   |  _____|      immutable borrow later used by call
   | |
75 | |         match event {
76 | |             Event::Key(Key::Char('a')) => {
77 | |                 println!("{} {} {} {}", "do something with a", 15, 1, true);
78 | |                 // tried to borrow as mutable
79 | |                 screen.println("hello there",15, 1, true);
   | |                 ------ second borrow occurs due to use of `screen` in closure
...  |
82 | |         }
83 | |     });
   | |______- immutable borrow occurs here

and if i make self mut inside handle_keys_loop to get rid of cannot borrow screen as mutable because it is also borrowed as immutable如果我在handle_keys_loop中进行self mut 以摆脱cannot borrow borrow screen as mutable because it is also borrowed as immutable

    pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
        + &mut self,
        - &self
....

i get this error我收到这个错误

error[E0499]: cannot borrow `screen` as mutable more than once at a time
  --> src/bin/terminal.rs:74:29
   |
74 |       screen.handle_keys_loop(|event| {
   |       -      ---------------- ^^^^^^^ second mutable borrow occurs here
   |       |      |
   |  _____|      first borrow later used by call
   | |
75 | |         match event {
76 | |             Event::Key(Key::Char('a')) => {
77 | |                 screen.println("hello there",15, 1, true);
   | |                 ------ second borrow occurs due to use of `screen` in closure
...  |
80 | |         }
81 | |     });
   | |______- first mutable borrow occurs here

what im trying to do: use the method handle_keys_loop of screen and pass screen inside the closure, which is passed to handle_keys_loop .我想做什么:使用screen的方法handle_keys_loop并在闭包内传递screen ,它被传递给handle_keys_loop basically, to use screen inside of screen .基本上,在screen内部使用screen

how do i achieve that?我该如何实现?

some people told me to use RefCell , but that didnt work out very well, i got BorrowError.有些人告诉我使用RefCell ,但效果不是很好,我得到了 BorrowError。

i will use any workaround to just use screen inside the closure which is passed to screen's method.我将使用任何解决方法来仅在传递给屏幕方法的闭包内使用屏幕。

thanks in advance.提前致谢。

One pattern I use to handle such a situation is to pass self: &mut Self back into the closure from handle and use that inside the closure.我用来处理这种情况的一种模式是将self: &mut Selfhandle传递回闭包,并在闭包内使用它。 A simplified version of your code:您的代码的简化版本:

struct Screen {}

struct Event {}

impl Screen {
    fn handle<F: FnMut(&mut Screen, Event)>(&mut self, mut handler: F) {
        handler(self, Event {})
    }

    fn print(&mut self) {}
}

fn main() {
    let mut screen = Screen {};
    screen.handle(|screen, _event| screen.print());
    screen.handle(|screen, _event| screen.print());
}

You can't do what you're trying to do because it violates Rust's rule that you can't mutate a value while something else has access to it.你不能做你想做的事,因为它违反了 Rust 的规则,即当其他东西可以访问它时你不能改变一个值。

However, your handle_keys_loop method doesn't even use self which means the &self parameter is redundant.但是,您的handle_keys_loop方法甚至不使用self这意味着&self参数是多余的。 There's no reason to give a function an argument it's not going to use (except when implementing a trait that requires it).没有理由给 function 一个它不会使用的参数(除非在实现需要它的特征时)。

Just remove the argument:只需删除参数:

    pub fn handle_keys_loop<F: FnMut(&Event) -> ()>(
        mut handler: F,
    ) {

And call it as Screen::handle_keys_loop(|event| {... }) .并将其称为Screen::handle_keys_loop(|event| {... })

Alternatively, make it a free function, external to Screen entirely, since it doesn't depend on Screen in any way.或者,将其设为完全在Screen外部的免费 function,因为它不以任何方式依赖于Screen

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM