是否可以检查锈蚀的闭合度是否相等?

问题描述

我刚接触锈,但是对于我正在从事的实践项目,我想实现一个像API这样的React useMemo,我想如果闭包的类型是静态的,并且捕获变量存储在某个地方,我应该不能检查是否相等?

类似的东西:

let cached = scope.use_memo(move || {
    complicated_computation(captured_variable)
});

其中use_memo类似于

pub fn use_memo<F: Fn() -> T + PartialEq + 'static,T: Clone + 'static>(&mut self,factory: F) -> &T

代码中的什么地方,我可以将工厂与以前存储的工厂函数进行比较,并确定是否需要重新运行工厂。

显然这是行不通的,因为闭包没有实现PartialEq,但是我想知道是否有办法实现它。

解决方法

我认为这是不可能的:Rust闭包在某种程度上是匿名类型,因此您无法在其上实现特征。而且,如果您使用更多的“显式”闭包,则可以在其中手工构建环境并传递一个简单的函数指针:

fn use_memo<T: PartialEq>(&mut self,env: T,func: fn(T))

您可以将它们进行比较:

fn main(){
    let a: fn(u8) -> u8 = |a: u8| a;
    let b: fn(u8) -> u8 = |a: u8| a % 2;
    println!("{}",a == b) -> false
}

但是您会遇到一个问题,即不同的回调将具有不同的环境,因此类型将不匹配,并且可能仍然无法比较它们。

,

我在防锈方面也很新,但是一个想法可能是拥有定义方法FactoryIdentifiable的自定义特征get_identifier

然后,您可以使用运算符重载并为此特征实现PartialEq,并修改闭包的类型签名以也需要该特征。

pub fn use_memo<F: Fn() -> T + FactoryIdentifiable,T: Clone + 'static>(&mut self,factory: F) -> &T
,

不。每个闭包都有一个单独的类型,即使它们是相同的,您也不能比较交叉类型。

正在寻找at a minimal example

fn main() {
    let b = 2;
    let a = if true {
        || println!("{}",b)
    } else {
        || println!("{}",b)
    };
}

我们收到一个编译器错误,可以帮助解释没有两个闭包,即使相同,也没有相同的类型

Compiling playground v0.0.1 (/playground)
error[E0308]: `if` and `else` have incompatible types
 --> src/main.rs:6:9
  |
3 |       let a = if true {
  |  _____________-
4 | |         || println!("{}",b)
  | |         -------------------- expected because of this
5 | |     } else {
6 | |         || println!("{}",b)
  | |         ^^^^^^^^^^^^^^^^^^^^ expected closure,found a different closure
7 | |     };
  | |_____- `if` and `else` have incompatible types
  |
  = note: expected type `[closure@src/main.rs:4:9: 4:29 b:_]`
          found closure `[closure@src/main.rs:6:9: 6:29 b:_]`
  = note: no two closures,even if identical,have the same type
  = help: consider boxing your closure and/or using it as a trait object

error: aborting due to previous error

您可以构建包含环境的结构并比较它们,而不是使用闭包,但是我建议您重新考虑您的问题,看看这是否是解决问题的最佳方法。