在Rust中比较函数是否相等的方法对比

3
我有一个函数,它以数字作为参数,然后返回基于该数字的函数。根据许多不同的事情,它可能会返回其中任何一个约50个函数,并且决定要返回哪个函数的情况变得非常复杂。因此,我想构建一些测试来确保返回正确的函数。到目前为止,我的代码大致如下。
fn pick_a_function(decider: u32) -> fn(&mut SomeStruct) {
    match decider {
        1 => add,
        2 => sub,
        _ => zero,
    }
}

fn add(x: &mut SomeStruct) {
    x.a += x.b;
}

fn sub(x: &mut SomeStruct) {
    x.a -= x.b;
}

fn zero(_x: &mut SomeStruct) {
    x.a = 0;
}

fn main() {
    let mut x = SomeStruct { a: 2, b: 3 };
    pick_a_function(1)(&mut x);

    println!("2 + 3 = {}", x.a);
}

#[cfg(test)]
mod tests {
    use super::*;

    fn picks_correct_function() {
        assert_eq!(pick_a_function(1), add);
    }
}

问题是这些函数似乎没有实现EqPartialEq特性,因此assert_eq!只会提示无法比较它们。我有哪些选项可以将返回的函数与正确的函数进行比较?

1
你在assert_eq中遇到了问题,因为缺少Debug trait,但测试函数相等性没有问题(这是指针比较)。你可以检查println!("{}", pick_a_function(1) == add);。你是否使用旧的rustc(如果是,则可能需要将其转换为usize)? - Denys Séguret
1
在昨晚深入研究后,我意识到函数确实实现了 PartialEq,但只有当它们没有附加到生命周期时才会这样。它们所有的参数都是可变结构体引用,这会隐式地将生命周期附加到函数上,从而防止它们成为 PartialEq。将函数强制转换为 usize 似乎可以解决这个问题。 - McKayla
2个回答

3
所以实际上,在Rust中,只要函数没有生命周期并且参数少于10个,就会自动实现PartialEq。这个限制是因为每种形式的函数签名都必须直接实现特征,因为编译器认为它们都是完全不相关的类型。
我返回的函数取一个可变引用到一个结构体,这会隐式给函数一个生命周期,所以它们不再有实现PartialEq的类型签名。但实际上,Rust在内部比较函数相等性时所做的只是将它们都强制转换为指针然后进行比较,所以我们可以做同样的事情。
#[cfg(test)]
mod tests {
    use super::*;

    fn picks_correct_function() {
        assert_eq!(
            pick_a_function(1) as usize,
            add as usize
        );
    }
}

0

你应该比较结果而不是函数本身,例如:

#[cfg(test)]
mod tests {
    use super::*;

    fn picks_correct_function() {
      let add_picked = pick_a_function(1);
      assert_eq!(add_picked(1,2), add(1,2));
    }
}

或者在更复杂的情况下,您可以比较输入,创建一个带有一个参数的函数和另一个带有两个参数的函数,尝试调用它们中的任何一个并查看是否出现编译器错误。


被返回的函数实际上并不返回结果,它们会改变作为参数传入的结构体,并且初始化其中一个结构体是非常昂贵的。我认为在代码样例中包含所有这些内容有点过于复杂了。 - McKayla
那么,比较这些结构体。我知道两个具有相同主体和签名的闭包不是相同类型。对于函数也必须如此。 - user11667416
我真的在寻找一种直接比较函数的方法。我不想处理比较两个结构体,它们都有几兆字节大小并需要大量初始化工作的情况。 - McKayla
你可以尝试为每个函数添加特定的返回值,然后按照我说的进行比较。或者创建一个过程宏属性,将函数作为项,并实现一个以字符串形式返回它们源代码的方法。你认为哪种方式更优秀就采用哪种方式。 - user11667416

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接