我想编写一个函数,实现以下功能:
接受形式为
我来自Haskell背景,在Haskell中,这可能是这样的:
将其翻译成更符合Rust语言特点的代码:
我收到了以下错误信息(在添加
fn(T) -> T
的闭包f
返回形式为fn(T, bool) -> T
的闭包,根据bool参数有条件地执行f
。我来自Haskell背景,在Haskell中,这可能是这样的:
conditionally :: (a -> a) -> a -> Bool -> a
conditionally f x True = f x
conditionally f x False = x
将其翻译成更符合Rust语言特点的代码:
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 } )
}
我这里漏了什么?在 Rust 中可行吗?我想知道我尝试做的事情是否有更具体的名称,而不仅仅是高阶函数,因为我很难找到这种问题的资源。
更新:我意识到“Rust 中的柯里化”将是一个好的搜索术语。虽然这不是柯里化的例子,但它将使用相同的语言特性,并会引导我到 vallentin 给出的答案。
conditional
传递给闭包的引用?这样做为什么会编译通过?即使没有引用,它也可以编译通过,但是考虑到F
不是引用,我希望调用conditional
不会按照所写的方式编译。 - user4815162342|x| {x}
和&|x| {x}
均实现了Fn(T) -> T
,这是该函数对其参数唯一的要求。 - Ivan C&
:) - vallentinconditional_increment
实例居然能工作,尽管我不确定如果它的参数是引用时Box::new
如何处理。 - Zoey Hewll