在 Rust 中,是否可以从一个函数 return 一个静态函数?

In Rust, is it possible to return a static function from a function?

假设我在 Rust 中有以下类型:

type UnOp = fn(u64) -> u64;

该类型允许我创建不同的一元操作:

const add1 : UnOp = |x| x + 1;
const mul2 : UnOp = |x| x * 2;

现在,假设我需要 add2add3add4 (...),用于不同的数字,在我的代码的不同位置。编写所有定义会很麻烦,因此,我编写了一个通用的 adder 函数:

fn adder(add : u64) -> UnOp {
  |x| x + add
}

这将允许我为任何数字写 add(2)add(3) 等:

// Prints 2 + 40
println!("result is: {}", adder(2)(40))

问题是:adder 实际上不是有效的 Rust 代码,因为 |x| ... 是一个闭包,而不是静态函数。为了让 adder 按我的意愿工作,我需要将 UnOp 修改为闭包:

type UnOp = Box<dyn Fn(u64) -> u64>;

fn adder(add : u64) -> UnOp {
  Box::new(move |x| x + add)
}

问题是:如果我知道 adder(N) 的每个用法都应用于静态值怎么办?

在那种情况下,创建动态闭包在计算方面会很浪费。不仅如此,Box<dyn ...> 使代码大大复杂化,甚至可能需要生命周期注解。我的问题是:

是否可以在不修改 UnOp 的原始定义的情况下创建 adder?也就是说,让 UnOp 成为静态函数,而不是闭包?

从逻辑上讲,没有理由不可能,只要 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);
}

这引发了 2 个错误:

- the type of const parameters must not depend on other generic parameters

- using function pointers as const generic parameters is forbidden

您可以使用 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));
}

Playground

Is it possible to create adder, without modifying the original definition of UnOp? That is, letting UnOp be a static function, NOT a closure?

既然你不解释为什么我会忽略这个要求。因为我认为你限制了你的选择。

您可能更喜欢巧妙地使用泛型和特征:

trait UnOp {
    fn call(&self, _: u64) -> u64;
}

impl<F> UnOp for F
where
    F: Fn(u64) -> u64,
{
    fn call(&self, x: u64) -> u64 {
        self(x)
    }
}

fn adder(add: u64) -> impl UnOp {
    move |x| x + add
}