Rust 中的部分应用程序有开销吗?

Fre*_*ios 6 closures rust

我喜欢使用部分应用程序,因为它允许(除其他外)拆分复杂的函数调用,这更具可读性。

部分应用示例:

fn add(x: i32, y: i32) -> i32 {
    x + y
}

fn main() {
    let add7 = |x| add(7, x);

    println!("{}", add7(35));
}
Run Code Online (Sandbox Code Playgroud)

这种做法有开销吗?

这是我喜欢做的事情(来自真实的代码):

fn foo(n: u32, things: Vec<Things>) {
    let create_new_multiplier = |thing| ThingMultiplier::new(thing, n); // ThingMultiplier is an Iterator
    let new_things = things.clone().into_iter().flat_map(create_new_multiplier);

    things.extend(new_things);
}
Run Code Online (Sandbox Code Playgroud)

这纯粹是视觉上的。我不喜欢铺满太多的东西。

the*_*472 5

在您的特定示例中,是的,extend 可以作为循环内联,其中包含另一个循环 for ,flat_map而后者只是将ThingMultiplier实例放入相同的堆栈槽中,n并持有and thing

但是你在这里吠叫错误的效率树。与其想知道一个包含两个字段的小结构的分配是否被优化掉了,不如想知道它的效率有多高clone,尤其是对于大输入。


She*_*ter 5

在使用之前定义闭包与直接定义和使用它之间不应该有性能差异。有一个类型系统差异——编译器不完全知道如何在没有立即调用的闭包中推断类型

在代码中:

let create_new_multiplier = |thing| ThingMultiplier::new(thing, n);
things.clone().into_iter().flat_map(create_new_multiplier)
Run Code Online (Sandbox Code Playgroud)

将与完全相同

things.clone().into_iter().flat_map(|thing| { 
    ThingMultiplier::new(thing, n)
})
Run Code Online (Sandbox Code Playgroud)

一般来说,使用闭包不应该有性能成本。这就是 Rust 所说的“零成本抽象”的意思:程序员自己写得再好不过了。

编译器将闭包转换Fn*为匿名结构上特征的实现。那时,所有正常的编译器优化都开始了。由于像单态化这样的技术,它甚至可能更快。这确实意味着您需要进行正常的分析以查看它们是否是瓶颈。