绑定函数参数和传递绑定函数的惯用法

时间:2017-03-26 12:58:58

标签: rust

是否有一种惯用的Rust方法来绑定函数参数并生成一个新函数?

例如,假设我有以下功能:

fn eq(a: i32) -> Box<Fn(i32) -> bool> {
    let target = a;  // copy
    Box::new(move |value| value == target)
}

fn evaluate(func: Box<Fn(i32) -> bool>, value: i32) -> bool {
    func(value)
}

Box使用的eq机制是一种将参数绑定到函数的合理方式,以便在evaluate中使用吗?例如像这样的东西:

let is_42 = eq(42);
assert_eq!(true, evaluate(is_42, 42));

还有生命的问题。我想知道在target中延长eq()的生命周期的正确语义是什么,所以它的生命周期与盒装函数的生命周期绑定。

1 个答案:

答案 0 :(得分:5)

  

是否有一种惯用的Rust方法来绑定函数参数并生成一个新函数?

是的,Rust有闭包,它实际上是函数+绑定环境。

因此,绑定一个函数参数或部分应用它只是形成一个闭包,它将用一些固定的参数调用这个函数。

  

Box使用eq机制是一种将参数绑定到函数的合理方式,以便在evaluate中使用吗?

现在是。

Rust关闭的问题是它们是Voldemort类型(即,无法命名的类型)。因此,虽然您可以为局部变量分配闭包,并让推断推断出类型,但您实际上无法从函数 1 返回它。

目前,解决方案是在这种情况下返回-> Box<Fn(..) -> ..>

但是,evaluate的签名是不必要的约束。您可以参考:

而不是Box
fn evaluate(f: &Fn(i32) -> bool, value: i32) -> bool { f(value) }

这将让可以直接调用evaluate的用户免费在堆上分配(Box执行)。

1 正在进行的工作允许将返回类型指定为-> impl SomeTrait,这样您就可以这样做。

  

还有生命的问题。我想知道在target中延长eq()的生命周期的正确语义是什么,所以它的生命周期与盒装函数的生命周期绑定。

无法延长一生;一生是描述性的,而不是规定性的:它只是表示实际生命周期的符号,而不是指定值应该具有的生命周期的方式。

对于闭包,你可能想要在闭包内move他们的环境;采取价值而不是参考。它应该解决大多数终身问题。

对于剩余的生命周期问题,您实际上是反过来并通过表示其环境的生命周期来约束闭包的类型:F: Fn(i32) -> bool + 'a标记F仅对{{1}有效}}