如何让Rust函数传播状态?

时间:2018-12-25 18:59:50

标签: rust

我需要编写一个Rust函数,该函数可以修改在更高函数中定义的状态,并将其从一个函数调用中传播到迭代器中的另一个函数(请参见下面的伪代码)。

在糟糕的C语言中,我将使用共享指针来执行此操作。当然,我知道为什么我不应该这样做,以及为什么我不能在Rust中做到这一点。

我发现的解决方法是添加一个额外的函数参数和一个额外的return参数:

fn f(inputs ..., s) {
    let mut s = s;
    // computations that rely on the value of s
    // ...
    outputs ..., s
}

fn main() {
    let mut s;
    for ... {
        let (outputs ..., x) = f(inputs ..., s);
        s = x;
    }
}

就编程风格而言,这似乎有点繁重,我希望可以使用更简单的构造(也许更单调)。我应该怎么写对我来说并不明显。

1 个答案:

答案 0 :(得分:2)

答案在于参考文献。

C中的共享指针带有关于何时何地可以这样做以及何时不可行的警告。 Rust具有借用检查器,以确保您没有对指针做任何愚蠢/不安全的事情,以防止人们在C语言中被咬伤的大部分问题。

例如,考虑一下您的代码略有变化(纯粹是为了使其能够编译)。可以这样重写它:

fn do_with(s: &mut u8, item: u8) {
    *s = *s + item;
}
fn main() {
    let mut s: u8 = 0;
    (1..10).for_each(|item| do_with(&mut s, item));
    println!("{}", s)
}

您会从C中识别出这种语法,但是它比C更安全,因为借位检查器可确保您的代码在任何给定时间仅具有一个可变引用。因此,该代码在每一步都被认为是明智的,并且可以编译。

您也可以按照自己的方式进行操作,方法是有效地践踏每次通话之间的价值。但是,这的确会导致代码的可读性降低,间接性级别更高。下面的示例:

fn do_with(s: u8, item: u8) -> u8 {
    s + item
}
fn main() {
    let mut s: u8 = 0;
    (1..10).for_each(|item| s = do_with(s, item));
    println!("{}", s)
}

在C语言中,指针的危险大部分在于对其进行维护和维护。由于Rust会为您检查并强制执行此操作(并且肯定会阻止您在使用futures时用脚射击),因此在很大程度上不会出现此问题。