Mai*_*tor 3 functional-programming rust
假设我在 Rust 中有以下类型:
type UnOp = fn(u64) -> u64;
Run Code Online (Sandbox Code Playgroud)
该类型允许我创建不同的一元运算:
const add1 : UnOp = |x| x + 1;
const mul2 : UnOp = |x| x * 2;
Run Code Online (Sandbox Code Playgroud)
现在,假设我需要在代码的不同位置使用add2
, add3
, (...), 来表示不同的数字。add4
编写所有定义会很麻烦,因此,我编写了一个通用adder
函数:
fn adder(add : u64) -> UnOp {
|x| x + add
}
Run Code Online (Sandbox Code Playgroud)
这将允许我为任何数字写add(2)
、add(3)
等:
// Prints 2 + 40
println!("result is: {}", adder(2)(40))
Run Code Online (Sandbox Code Playgroud)
问题是:adder
实际上不是有效的 Rust 代码,因为它|x| ...
是一个闭包,而不是静态函数。为了按照adder
我想要的方式工作,我需要修改UnOp
为闭包:
type UnOp = Box<dyn Fn(u64) -> u64>;
fn adder(add : u64) -> UnOp {
Box::new(move |x| x + add)
}
Run Code Online (Sandbox Code Playgroud)
问题是:如果我知道 的每个用法都adder(N)
应用于静态值怎么办?
在这种情况下,创建动态闭包在计算方面将是浪费的。不仅如此,使Box<dyn ...>
代码变得非常复杂,甚至可能需要生命周期注释。我的问题是:
是否可以adder
在不修改 的原始定义的情况下创建UnOp
?也就是说,letUnOp
是一个静态函数,而不是一个闭包?
从逻辑上讲,没有理由不可能,只要 的参数adder
是静态的,Rust 就应该能够在编译时扩展它,以生成每个特定的实例。
编辑:附加详细信息
@Netwave 的答案提出的一个很好的解决方案是使用通用常量,它解决了我给出的具体示例的这个问题。遗憾的是,如果UnOp
是多态的,或者常量参数本身就是一个函数,它就不起作用:
type UnOp<A> = fn(A) -> A;
pub fn adder<const ADD: u64>() -> UnOp<u64> {
|x| ADD + x
}
pub fn apply<A, const op : UnOp<A>, const x : A>() -> A {
return op(x);
}
Run Code Online (Sandbox Code Playgroud)
这会引发 2 个错误:
- the type of const parameters must not depend on other generic parameters
- using function pointers as const generic parameters is forbidden
Run Code Online (Sandbox Code Playgroud)
您可以使用以下方法来完成const Generics
:
type UnOp = fn(u64) -> u64;
const fn adder<const ADD: u64>(x: u64) -> u64 {
ADD + x
}
fn main() {
let add_1: UnOp = adder::<1>;
println!("{}", add_1(1));
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
582 次 |
最近记录: |