generics - 在 Rust 中实现 len() 函数的类型的通用较长函数

标签 generics rust borrow-checker

我试图做的是创建通用函数来比较具有长度的事物的两个实例。

我的代码:

fn main() {
    let vec1 = vec!(1, 2, 3);
    let vec2 = vec!(1, 2, 3, 4);
    println!("Longest vector is: {:?}", longer_vec_gen(&vec1, &vec2));
    println!("Longest iterator is {:?}", longer_exact_size_iterator(&vec1.iter(), &vec2.iter()))
}

fn longer_vec_gen<'a, T>(x: &'a Vec<T>, y: &'a Vec<T>) -> &'a Vec<T> {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn longer_exact_size_iterator<'a, T: ExactSizeIterator>(x: &'a T, y: &'a T) -> &'a T {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

这两个函数都有效,但是第一个函数仅适用于Vec,所以我想向前迈出一步,对任何有长度的东西都这样做。第二个有点实现了这一点,但现在我被迫在调用这个函数时在参数上使用 .iter() ,这是我希望避免的。

另一个问题是我无法将字符串字符串文字传递给此函数。

我希望实现的是创建函数更长,该函数将采用任意两个已实现函数.len()的元素,因此此代码运行时不会出现错误:

fn main() {
    let vec1 = vec!(1, 2, 3);
    let vec2 = vec!(1, 2, 3, 4);
    println!("Longer vector is: {:?}", longer(&vec1, &vec2));

    let string1 = String::from("abcd");
    let string2 = String::from("xyz");
    println!("Longest string is : {:?}", longer(&string1, &string2))
}

fn longer(...) {
...
}

最佳答案

but right now I'm forced to use .iter() on parameters while calling this function which I would love to avoid

您可以通过限制 IntoIterator 来解决该特定问题。这有点棘手,因为您想要返回传递给函数的引用,但 IntoIterator 消耗了它的接收器。您可以通过要求类型为 IntoIterator + Copy 来实现此目的。由于 Copy 是通过共享引用来满足的,因此此函数适用于对大多数(如果不是全部)标准容器类型的引用:

fn longer_exact_size_iterator<T, U>(x: T, y: T) -> T
where T: IntoIterator<IntoIter=U> + Copy,
    U: ExactSizeIterator,
{
    if x.into_iter().len() > y.into_iter().len() {
        x
    } else {
        y
    }
}

现在您可以执行longer_exact_size_iterator(&vec1, &vec2)

( Playground )

如果您想要一个适用于任何带有 .len() 的变体,但可能没有精确大小的迭代器,那么您必须编写自己的特征并在类型上实现它你想要处理;它不会是自动的。例如:

pub trait HasLength {
    fn len(self) -> usize;
}

impl<T> HasLength for &Vec<T> {
    fn len(self) -> usize {
        Vec::len(self)
    }
}

impl<T> HasLength for &[T] {
    fn len(self) -> usize {
        <[T]>::len(self)
    }
}

// And so on...

fn longer<T: HasLength + Copy>(x: T, y: T) -> T {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

( Playground )

关于generics - 在 Rust 中实现 len() 函数的类型的通用较长函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72923321/

相关文章:

rust - 我是否必须为拥有(易于使用)和借用(更高效)的数据结构创建不同的结构?

rust - 安全的重要数据依赖项/自定义引用?

java - 无法创建 Map.Entry 类型的泛型类

Java 创建通用对象的映射

java - 为什么我不能在这段代码中使用 Collections.max() 函数? - java

rust - 调用 Option::unwrap 时无法移出 `&mut` 指针的取消引用

generics - 创建新的通用结构的正确方法是什么?

rust - 嵌套数组索引中的 "cannot borrow as immutable because it is also borrowed as mutable"是什么意思?

rust - "borrowed data cannot be stored outside of its closure"是什么意思?

java - 方法重载时复制方法