【发布时间】:2021-01-01 07:18:55
【问题描述】:
我正在尝试创建一个函数来执行以下操作:
接受fn(T) -> T 形式的闭包fn(T) -> T
返回 fn(T, bool) -> T 形式的闭包,根据 bool 参数有条件地执行 f。
我来自 haskell-ish 背景,在 Haskell 中,这将是这样的:
conditionally :: (a -> a) -> a -> Bool -> a
conditionally f x True = f x
conditionally f x False = x
把它翻译成更像生锈的东西:
conditionally :: ((t) -> t) -> ((t, Bool) -> t)
conditionally f = \(x, b) -> if b then (f x) else (x)
我在 rust 中尝试了以下操作:
fn conditionally<T>(f: &'static (dyn Fn(T) -> T + 'static)) -> Box<dyn Fn(T, bool) -> T> {
Box::new(&|x, b| if b { f(x) } else { x } )
}
并被告知使用move 关键字来确保闭包拥有f 的所有权。但是,以下仍然不起作用:
fn conditional<T>(f: &'static (dyn Fn(T) -> T + 'static)) -> Box<dyn Fn(T, bool) -> T> {
Box::new(&move|x, b| if b { f(x) } else { x } )
}
我收到以下错误(这也出现在添加 move 之前):
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:216:5
|
216 | Box::new(&move|x, b| if b { f(x) } else { x } )
| ^^^^^^^^^^-----------------------------------^^
| | |
| | temporary value created here
| returns a value referencing data owned by the current function
我在想“当前函数拥有的数据”要么是我定义的闭包,要么是我移动的 f,但我不知道它是如何适合的在一起。
作为烟雾检查,我确保我能够将我在函数体中定义的更简单的闭包装箱,并编译以下代码:
fn conditional_increment() -> Box<dyn Fn(i32, bool) -> i32> {
Box::new(&|x, b| if b { x + 1 } else { x } )
}
我在这里缺少什么?这可能生锈吗? 我还想知道我正在尝试做的事情是否有一个比简单的高阶函数更具体的名称,因为我正在努力寻找这类问题的资源。
更新:我意识到“currying in rust”本来是一个很好的搜索词。虽然这不是柯里化的示例,但它会使用相同的语言功能,并且会引导我得到 vallentin 给出的答案。
【问题讨论】:
标签: rust closures higher-order-functions