我试图做的是创建通用函数来比较具有长度的事物的两个实例。
我的代码:
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/