在 Rust 中,是否可以从函数返回静态函数?

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)

Net*_*ave 5

您可以使用以下方法来完成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)

操场