简体   繁体   English

在 Rust 中的迭代器上编写 sum 的通用实现

[英]Writing generic implementation of sum on an iterator in Rust

I have been learning Rust, coming from a Swift, C and C++ background.我一直在学习 Rust,来自 Swift、C 和 C++ 背景。 I feel like I have a basic understanding of ownership, borrowing and traits.我觉得我对所有权、借用和特征有了基本的了解。 To exercise a bit, I decided to implement a sum function on a generic slice [T] where T has a default value and can be added to itself.为了练习一下,我决定在通用切片[T]上实现sum function,其中T具有默认值并且可以添加到自身。

This is how far I got:这是我走了多远:

trait Summable {
    type Result;
    fn sum(&self) -> Self::Result;
}

impl<T> Summable for [T]
where
    T: Add<Output = T> + Default,
{
    type Result = T;

    fn sum(&self) -> T {
        let x = T::default();
        self.iter().fold(x, |a, b| a + b)
    }
}

Compiler complains with expected type parameter T, found &T for a + b .编译器抱怨expected type parameter T, found &T for a + b

I understand why the error happens, but not exactly how to fix it.我明白为什么会发生错误,但不知道如何解决它。 Yes, the type of x is T .是的, x的类型是T It cannot be &T because, if nothing else, if the slice is empty, that's the value that is returned and I cannot return a reference to something created inside the function. Plus, the default function returns a new value that the code inside the function owns.它不能是&T因为,如果没有别的,如果切片是空的,那就是返回的值,我不能返回对 function 内部创建的东西的引用。另外,默认 function 返回一个新值,function 内部的代码拥有。 Makes sense.说得通。 And yes, b should be a shared reference to the values in the slice since I don't want to consume them (not T ) and I don't want to mutate them (not &mut T ).是的, b应该是对切片中值的共享引用,因为我不想使用它们(不是T )并且我不想改变它们(不是&mut T )。

But that means I need to add T to &T , and return a T because I am returning a new value (the sum) which will be owned by the caller.但这意味着我需要将T添加到&T ,并返回一个T因为我要返回一个将由调用者拥有的新值(总和)。 How?如何?

PS: Yes, I know this function exists already. PS:是的,我知道这个 function 已经存在了。 This is a learning exercise.这是一个学习练习。

The std::ops::Add trait has an optional Rhs type parameter that defaults to Self : std::ops::Add特性有一个可选的Rhs类型参数,默认为Self

pub trait Add<Rhs = Self> {
    type Output;
    fn add(self, rhs: Rhs) -> Self::Output;
}

Because you've omitted the Rhs type parameter from the T: Add<Output = T> bound, it defaults to T : hence to your a you can add a T , but not an &T .因为您从T: Add<Output = T>绑定中省略了Rhs类型参数,所以它默认为T : 因此您可以在a中添加T ,但不能添加&T

Either specify that T: for<'a> Add<&'a T, Output = T> ;要么指定T: for<'a> Add<&'a T, Output = T> ; or else somehow obtain an owned T from b , eg via T: Copy or T: Clone .或者以某种方式从b获取拥有的T ,例如通过T: CopyT: Clone

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM