是否可以将对象方法作为参数传递给函数并将其绑定到对象?

时间:2016-05-23 12:59:54

标签: rust

是否可以绑定到对象方法?例如,如果向量中存在某个项目,我有一个向量和许多函数可以执行某些操作。我会按如下方式实现它:

fn perform_if_exists(item: u8, vector: &Vec<u8>, func: fn(usize)) {
    let idx = vector.iter().position(|i| *i == item );
    match idx {
        Some(i) => func(i), 
        None    => {},
    }
}

fn main() {
    let v: Vec<u8> = vec![1, 2, 3];
    perform_if_exists(1, &v, Vec<_>::remove);
}

但它会带来很多错误。我认为它们是合理的,但这是因为我不明白如何将vector的方法作为参数添加到函数中。

2 个答案:

答案 0 :(得分:5)

  

是否可能

当然可以。您必须首先修复多个级联错误:

  1. 语法无效:Do While not rs.EOF i = i + 1 With frmOne.Controls.Add("Forms.CheckBox.1", "Version" & i, True) .Caption = rs!versNo & "#" & rs!versFrom .tag = rs!versNo & "_" & rs!FiD & ".pdf" End With rs.MoveNext Loop 无效。
  2. 不兼容的参数类型:Vec<_>::remove修改 a Vec::remove ,因此您必须以某种方式传递Vec
  3. 可变性:Vec 修改一个Vec::remove,因此您必须声明该函数可以这样做。
  4. Vec返回已删除的值,因此您必须允许该函数返回一个值,即使它已被丢弃。
  5. Vec::remove

    我切换到通用,因为通常你会接受闭包。函数指针很好,但限制性更强。

答案 1 :(得分:4)

Rust中的方法只不过是一个函数,它也需要第一个self参数。方法Vec::remove有两个参数:&mut selfindex: usizeself参数始终为Self类型,在这种情况下为Vec<u8>Vec::<u8>::remove的完整类型为:fn(&mut Vec<u8>, usize) -> u8(是的,它还会返回已删除的元素)。

更改代码中的类型(+一些小错误)之后,它可以工作:

//                                      vvv-- has to be mutable
fn perform_if_exists(item: u8, vector: &mut Vec<u8>, func: fn(&mut Vec<u8>, usize) -> u8) {
    let idx = vector.iter().position(|i| *i == item );
    match idx {
        Some(i) => { 
            func(vector, i);
        }, 
        None    => {},
    }
}

fn main() {
    let mut v: Vec<u8> = vec![1, 2, 3];
    perform_if_exists(1, &mut v, Vec::remove);
}

但是fn(...) -> ...类型是原始指针类型,只适用于普通函数。通常,您还希望允许用户传递可调用的任何&#34;,如闭包。完全出于这个目的有一些特征:Fn(...) -> ...

让我提出另一种解决方案:

fn perform_if_exists<T, F, R>(item: T, vector: &mut Vec<T>, func: F) -> Option<R>
    where F: FnOnce(&mut Vec<T>, usize) -> R,
          T: PartialEq
{
    let idx = vector.iter().position(|i| *i == item );
    idx.map(|i| func(vector, i))
}

这个解决方案更通用,因为它允许任意项目类型,任意&#34;可调用&#34;类型并返回给定函数返回的值。请注意,main功能没有变化;解决方案更通用,但所有旧的用途仍然有用。