如何使用匿名lambda函数重写以下rust代码?

xxls0lw8  于 2023-05-07  发布在  其他
关注(0)|答案(4)|浏览(93)

我有下面的代码在生 rust 和这一个我的工作。这里我定义了函数,它改变了通过引用传递的参数。

fn inc (v: &mut i32){
    *v+=1;
}

fn main() {
    let mut n = 0;
    // let mut inc = || n += 1;

    inc(&mut n); // call the closure to increment n
    println!("n = {}", n); // prints "n = 1"

    inc(&mut n); // call the closure again to increment n
    println!("n = {}", n); // prints "n = 2"

    inc(&mut n); // call the closure again to increment n
    println!("n = {}", n); // prints "n = 3"
}

我尝试使用命名函数而不是匿名函数(我的问题中的第一个例子)
在上面的代码示例中,我有函数inc,而at通过引用获取参数并递增它。有没有可能定义匿名lambda来完成同样的任务?理想情况下,它将具有类似于以下代码的内容:

fn main() {
    let mut n = 0;    let mut inc = || n += 1;

    inc(); // call the closure to increment n
    println!("n = {}", n); // prints "n = 1"

    inc(); // call the closure again to increment n
    println!("n = {}", n); // prints "n = 2"

    inc(); // call the closure again to increment n
    println!("n = {}", n); // prints "n = 3"
}
oxf4rvwz

oxf4rvwz1#

为什么在闭包活动的时候,它被借用为可变的,而不仅仅是在调用的时候?

let mut inc = || n += 1; // captures a mutable reference to n and creates a closure that can mutate it

闭包也需要独占访问n,就像inc函数一样。因此,它将可变引用视为在闭包的生存期内被借用,即使闭包没有被立即调用。
一个解决方案是,因为你没有给lambda函数带参数,所以带一个引用参数。我们不能将n借用为不可变的,因为在您的代码示例中,它也被借用为可变的。下面是一个lambda函数,它“修改引用传递的变量”Playground

fn main() {
    let mut n = 0;

    let inc = |v: &mut i32| {
        *v += 1;
    };

    inc(&mut n);
    println!("n = {}", n); // prints "n = 1"

    inc(&mut n);
    println!("n = {}", n); // prints "n = 2"

    inc(&mut n);
    println!("n = {}", n); // prints "n = 3"
}
j2datikz

j2datikz2#

也许你可以接受n作为参数。但是如果你真的需要在闭包中捕获它,你可以使用interior mutability

use std::cell::Cell;

fn main() {
    let n = Cell::new(0);
    let inc = || n.set(n.get() + 1);

    inc(); // call the closure to increment n
    println!("n = {}", n.get()); // prints "n = 1"

    inc(); // call the closure again to increment n
    println!("n = {}", n.get()); // prints "n = 2"

    inc(); // call the closure again to increment n
    println!("n = {}", n.get()); // prints "n = 3"
}

或者对于更复杂的类型,Cell不够,可以使用RefCell

use std::cell::RefCell;

fn main() {
    let n = RefCell::new(0);
    let inc = || *n.borrow_mut() += 1;

    inc(); // call the closure to increment n
    println!("n = {}", n.borrow()); // prints "n = 1"

    inc(); // call the closure again to increment n
    println!("n = {}", n.borrow()); // prints "n = 2"

    inc(); // call the closure again to increment n
    println!("n = {}", n.borrow()); // prints "n = 3"
}
watbbzwu

watbbzwu3#

你不能像这样借用引用,相反,你可以定义lambda并将可变引用传递给它,如下所示:

fn main() {
    let mut n = 0;
    let inc = |n_ref: &mut i32| {
        *n_ref += 1;
    };

    inc(&mut n); // call the closure to increment n
    println!("n = {}", n); // prints "n = 1"

    inc(&mut n); // call the closure again to increment n
    println!("n = {}", n); // prints "n = 2"

    inc(&mut n); // call the closure again to increment n
    println!("n = {}", n); // prints "n = 3"
}
ih99xse1

ih99xse14#

以下代码使用了unsafe mutable static works

static mut n: i32 = 0;

fn main() {
    unsafe fn inc() {
        n = n+ 1;
    }

    unsafe {
      inc();
      println!("n = {}", n); // prints "n = 1"
    } 
    unsafe {
      inc();
      println!("n = {}", n); // prints "n = 2"
    }
    unsafe {
      inc();
      println!("n = {}", n); // prints "n = 3"
    }
}

inc函数也可以与main函数分离:

static mut n: i32 = 0;

unsafe fn inc() {
        n = n+ 1;
    }

fn main() {
    unsafe {
      inc();
      println!("n = {}", n); // prints "n = 1"
    } 
    unsafe {
      inc();
      println!("n = {}", n); // prints "n = 2"
    }
    unsafe {
      inc();
      println!("n = {}", n); // prints "n = 3"
    }
}

编辑:但是,unsafe不应该用于诸如递增数字之类的琐碎原因,正如@SilvioMayolo在下面的评论中指出的那样。上面的代码只是为了展示什么是可能的。

相关问题