Extend Iterator with a "mean" method - rust

I'm trying to implement a mean method for Iterator, like it is done with sum.
However, sum is Iterator method, so I decided to implement trait for any type that implements Iterator:
pub trait Mean<A = Self>: Sized {
fn mean<I: Iterator<Item = A>>(iter: I) -> f64;
}
impl Mean for u64 {
fn mean<I: Iterator<Item = u64>>(iter: I) -> f64 {
//use zip to start enumeration from 1, not 0
iter.zip((1..))
.fold(0., |s, (e, i)| (e as f64 + s * (i - 1) as f64) / i as f64)
}
}
impl<'a> Mean<&'a u64> for u64 {
fn mean<I: Iterator<Item = &'a u64>>(iter: I) -> f64 {
iter.zip((1..))
.fold(0., |s, (&e, i)| (e as f64 + s * (i - 1) as f64) / i as f64)
}
}
trait MeanIterator: Iterator {
fn mean(self) -> f64;
}
impl<T: Iterator> MeanIterator for T {
fn mean(self) -> f64 {
Mean::mean(self)
}
}
fn main() {
assert_eq!([1, 2, 3, 4, 5].iter().mean(), 3.);
}
Playground
The error:
error[E0282]: type annotations needed
--> src/main.rs:26:9
|
26 | Mean::mean(self)
| ^^^^^^^^^^ cannot infer type for `Self`
Is there any way to fix the code, or it is impossible in Rust?

like it is done with sum
Let's review how sum works:
pub fn sum<S>(self) -> S
where
S: Sum<Self::Item>,
sum is implemented on any iterator, so long as the result type S implements Sum for the iterated value. The caller gets to pick the result type. Sum is defined as:
pub trait Sum<A = Self> {
pub fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = A>;
}
Sum::sum takes an iterator of A and produces a value of the type it is implemented from.
We can copy-paste the structure, changing Sum for Mean and put the straightforward implementations:
trait MeanExt: Iterator {
fn mean<M>(self) -> M
where
M: Mean<Self::Item>,
Self: Sized,
{
M::mean(self)
}
}
impl<I: Iterator> MeanExt for I {}
trait Mean<A = Self> {
fn mean<I>(iter: I) -> Self
where
I: Iterator<Item = A>;
}
impl Mean for f64 {
fn mean<I>(iter: I) -> Self
where
I: Iterator<Item = f64>,
{
let mut sum = 0.0;
let mut count: usize = 0;
for v in iter {
sum += v;
count += 1;
}
if count > 0 {
sum / (count as f64)
} else {
0.0
}
}
}
impl<'a> Mean<&'a f64> for f64 {
fn mean<I>(iter: I) -> Self
where
I: Iterator<Item = &'a f64>,
{
iter.copied().mean()
}
}
fn main() {
let mean: f64 = [1.0, 2.0, 3.0].iter().mean();
println!("{:?}", mean);
let mean: f64 = std::array::IntoIter::new([-1.0, 2.0, 1.0]).mean();
println!("{:?}", mean);
}

You can do it like this, for example:
pub trait Mean {
fn mean(self) -> f64;
}
impl<F, T> Mean for T
where T: Iterator<Item = F>,
F: std::borrow::Borrow<f64>
{
fn mean(self) -> f64 {
self.zip((1..))
.fold(0.,
|s, (e, i)| (*e.borrow() + s * (i - 1) as f64) / i as f64)
}
}
fn main() {
assert_eq!([1f64, 2f64, 3f64, 4f64, 5f64].iter().mean(), 3.);
assert_eq!(vec![1f64, 2f64, 3f64, 4f64, 5f64].iter().mean(), 3.);
assert_eq!(vec![1f64, 2f64, 3f64, 4f64, 5f64].into_iter().mean(), 3.);
}
I used Borrow trait to support iterators over f64 and &f64.

Related

Generic trait for u8 iterators with function that returns a bool iterator

I have this code:
pub trait BytesToBits<T>: Iterator<Item = u8>
where
T: Iterator<Item = bool>,
{
fn bits(&mut self) -> T;
}
impl<T> BytesToBits<T> for dyn Iterator<Item = u8>
where
T: Iterator<Item = bool>,
{
fn bits(&mut self) -> T {
self.flat_map(|byte| (0..8).map(move |offset| byte & (1 << offset) != 0))
}
}
However, compiling it results in:
error[E0308]: mismatched types
--> src/bitstream.rs:13:9
|
8 | impl<T> BytesToBits<T> for dyn Iterator<Item = u8>
| - this type parameter
...
12 | fn bits(&mut self) -> T {
| - expected `T` because of return type
13 | self.flat_map(|byte| (0..8).map(move |offset| byte & (1 << offset) != 0))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found struct `FlatMap`
|
= note: expected type parameter `T`
found struct `FlatMap<&mut (dyn Iterator<Item = u8> + 'static), Map<std::ops::Range<{integer}>, [closure#src/bitstream.rs:13:41: 13:54]>, [closure#src/bitstream.rs:13:23: 13:29]>`
I am new to Rust and do not know what I exactly did wrong there and how to resolve the issue.
My goal is to have a trait BytesToBits that extends all Iterator<Item = u8> by providing them with a method bits() that returns an Iterator<Item = bool>.
I think that this solves your problem:
pub trait BytesToBits<T>: Iterator<Item=u8>
where
T: Iterator<Item=bool>,
{
fn bits(&mut self) -> Box<dyn Iterator<Item=bool> + '_>;
}
impl<T> BytesToBits<T> for dyn Iterator<Item=u8>
where
T: Iterator<Item=bool>,
{
fn bits(&mut self) -> Box<dyn Iterator<Item=bool> + '_> {
Box::new(self.flat_map(|byte| (0..8).map(move |offset| byte & (1 << offset) != 0)))
}
}
But if someone will find explanation why the first approach is wrong I will be grateful :D
Thanks for the comments and the answer.
I think my issue again boiled down to the fact, that you cannot return traits from functions of traits [1].
I solved it now with a custom iterator:
pub trait BytesToBits<T>
where
T: Iterator<Item = bool>,
{
fn bits(self) -> T;
}
impl<T> BytesToBits<BytesToBitsIterator<T>> for T
where
T: Iterator<Item = u8>,
{
fn bits(self) -> BytesToBitsIterator<T> {
BytesToBitsIterator::from(self)
}
}
pub struct BytesToBitsIterator<T>
where
T: Iterator<Item = u8>,
{
bytes: T,
current: Option<u8>,
index: u8,
}
impl<T> From<T> for BytesToBitsIterator<T>
where
T: Iterator<Item = u8>,
{
fn from(bytes: T) -> Self {
Self {
bytes,
current: None,
index: 0,
}
}
}
impl<T> Iterator for BytesToBitsIterator<T>
where
T: Iterator<Item = u8>,
{
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
if self.index > 7 {
self.current = None;
self.index = 0;
}
let current = match self.current {
None => match self.bytes.next() {
None => {
return None;
}
Some(byte) => {
self.current = Some(byte);
byte
}
},
Some(byte) => byte,
};
let bit = current & (1 << self.index) != 0;
self.index += 1;
Some(bit)
}
}
[1] Implement trait that has function which return traits

Return only an owned type from a trait method that can accept an owned or borrowed value as input

I want to have a trait that can be implemented for T and &T but has methods that always return T.
What I would like to do is something like this
use std::borrow::ToOwned;
trait Foo<X: ToOwned> {
fn f(&self, x: X) -> f64;
fn g(&self) -> X::Owned;
}
struct Float(f64);
impl Foo<f64> for Float {
fn f(&self, x: f64) -> f64 {
x + self.0
}
fn g(&self) -> f64 {
self.0 * 2.0
}
}
struct List(Vec<f64>);
impl Foo<&Vec<f64>> for List {
fn f(&self, x: &Vec<f64>) -> f64 {
x.iter().sum()
}
// Error here - `&Vec<f64>` return type expected
fn g(&self) -> Vec<f64> {
self.0.iter().map(|&x| 2.0 * x).collect()
}
}
fn main() {
let float = Float(2.0);
println!("{} {}", float.f(3.0), float.g());
let list = List(vec![0.0, 1.0, 2.0]);
println!("{} {:?}", list.f(&vec![1.0, 2.0]), list.g());
}
I know that one option is to have a trait that defines the output type like so
trait FooReturn {
type Output;
}
trait Foo<X: FooReturn> {
fn f(&self, x: X) -> f64;
fn g(&self) -> X::Output;
}
then implement the trait for all relevant types, but I was wondering if there was a more standard/robust way to do this.
This is how you would do it once specialization is complete. Meanwhile, I couldn't even get a simple working example to compile on 1.55.0-nightly.
#![feature(specialization)]
trait MaybeOwned {
type Owned;
}
default impl<X> MaybeOwned for X {
type Owned = X;
}
impl<'a, X> MaybeOwned for &'a X {
type Owned = X;
}
trait Foo<X: MaybeOwned> {
fn f(&self, x: &X) -> f64;
fn g(&self) -> <X as MaybeOwned>::Owned;
}

Multiply trait implementations in Rust

I'm trying to implement trait IDimTransformer for different generic types of traits IDimOffset0Transformer and IDimOffset1Transformer but compiler give me error
trait IDimTransformer {
fn get_offset_x(&self, x: i32) -> i32;
fn get_offset_z(&self, z: i32) -> i32;
}
trait IDimOffset0Transformer : IDimTransformer {}
trait IDimOffset1Transformer : IDimTransformer {}
impl<T: IDimOffset0Transformer> IDimTransformer for T {
fn get_offset_x(&self, x: i32) -> i32 {
return x;
}
fn get_offset_z(&self, z: i32) -> i32 {
return z;
}
}
impl<T: IDimOffset1Transformer> IDimTransformer for T {
fn get_offset_x(&self, x: i32) -> i32 {
return x - 1;
}
fn get_offset_z(&self, z: i32) -> i32 {
return z - 1;
}
}
Example of use
struct Layer {}
impl IDimOffset1Transformer for Layer{}
fn some_func(dim: &impl IDimTransformer, x: i32, z: i32) -> i32 {
return dim.get_offset_x(x) + dim.get_offset_z(x);
}
fn some_func_1(layer: &Layer, x: i32, z: i32) -> i32 {
return some_func(layer, x, z);
}
Compiler error
error[E0119]: conflicting implementations of trait `layer::IDimTransformer`:
--> src/layer.rs:59:1
|
49 | impl<T: IDimOffset0Transformer> IDimTransformer for T {
| ----------------------------------------------------- first implementation here
...
59 | impl<T: IDimOffset1Transformer> IDimTransformer for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
I think the pattern you are looking for looks like this in rust:
trait Transformer {
fn get_offset_x(x: i32) -> i32;
fn get_offset_z(z: i32) -> i32;
}
struct Offset0Transformer;
impl Transformer for Offset0Transformer {
fn get_offset_x(x: i32) -> i32 {
x
}
fn get_offset_z(z: i32) -> i32 {
z
}
}
struct Offset1Transformer;
impl Transformer for Offset1Transformer {
fn get_offset_x(x: i32) -> i32 {
x - 1
}
fn get_offset_z(z: i32) -> i32 {
z - 1
}
}
struct Layer { x: i32, z: i32 };
impl Layer {
fn add_transformed<T: Transformer>(&self) -> i32 {
T::get_offset_x(self.x) + T::get_offset_z(self.z)
}
}
fn main() {
let layer = Layer { x: 5, z: 2 };
let result = layer.add_transformed::<Offset1Transformer>();
println!("got: {}", result);
}
Most of the time you won't need this though. Thinking through what your code is trying to do and thinking of a simpler way usually gets you smaller better code.

Using Rayon into_par_iter().sum() with custom struct

I'm trying to get use Rayon::prelude::into_par_iter to sum up a bunch of instances of a struct. I've implemented std::iter::Sum for the struct, but am still running into an error. Here is my example code;
use std::iter::Sum;
use rayon::prelude::*;
pub struct TestStruct {
val: f32,
}
impl TestStruct {
pub fn new(v: f32) -> Self {
Self { val: v }
}
}
impl<'a> Sum<&'a Self> for TestStruct {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self { val: 0. }, |a, b| Self {
val: a.val + b.val,
})
}
}
fn main() {
let default_val: f32 = 1.1;
let sum: TestStruct = (0..5).into_par_iter().map(|&default_val| {
TestStruct::new(default_val)
})
.sum();
println!("{}", sum.val);
}
and I am told the trait 'std::iter::Sum' is not implemented for 'TestStruct', but I think I am implementing it. Am I missing something here?
Two small compounded issues. One is that the std::iter::Sum is defined as:
pub trait Sum<A = Self> {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = A>;
}
The Self here refers to whatever the struct gets the implementation and the default generic parameter has already been filled in. You don't need to specify it any more if implementing Sum for struct itself.
The other is that the map closure parameter default_val, which is an integer, shadows the previous float one with the same name. Since TestStruct::new expects a f32, it leads to a type error.
This works:
impl Sum for TestStruct {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
...
}
}
fn main() {
let default_val: f32 = 1.1;
let sum: TestStruct = (0..5)
.into_par_iter()
.map(|_| TestStruct::new(default_val))
.sum();
println!("{}", sum.val);
}

Require trait implementations to be convertible between each other

I'm trying to have a Rust trait X which requires that anyone implementing X can convert to other implementations of X.
So I'm trying to make the declaration of X enforce this like so:
trait X<T> : From<T> where T: X {}
But the compiler is telling me that it doesn't find any type arguments in my specification of T, because T: X needs some type information T: X<...>. But this way there will always be one type argument too little; e.g.
trait X<T, U> : From<T> where T: X<U> {}
Can I get around this in some way? Doing where T: X<_> is not allowed.
Rather than trying to restrict the implementers, I think it would be simpler to provide the implementation as part of the trait:
trait Length {
fn unit_in_meters() -> f64;
fn value(&self) -> f64;
fn new(value: f64) -> Self;
fn convert_to<T:Length>(&self) -> T {
T::new(self.value() * Self::unit_in_meters() / T::unit_in_meters())
}
}
struct Mm {
v: f64,
}
impl Length for Mm {
fn unit_in_meters() -> f64 { 0.001 }
fn value(&self) -> f64 { self.v }
fn new(value: f64) -> Mm {
Mm{ v: value }
}
}
struct Inch {
v: f64,
}
impl Length for Inch {
fn unit_in_meters() -> f64 { 0.0254 }
fn value(&self) -> f64 { self.v }
fn new(value: f64) -> Inch {
Inch{ v: value }
}
}
fn main() {
let foot = Inch::new(12f64);
let foot_in_mm: Mm = foot.convert_to();
println!("One foot in mm: {}", foot_in_mm.value());
}
Play link
For fun, with the associated_consts feature you can swap the method for a constant conversion factor.
#![feature(associated_consts)]
trait Length {
const UNIT_IN_METERS: f64;
fn value(&self) -> f64;
fn new(value: f64) -> Self;
fn convert_to<T:Length>(&self) -> T {
T::new(self.value() * Self::UNIT_IN_METERS / T::UNIT_IN_METERS)
}
}
struct Mm {
v: f64,
}
impl Length for Mm {
const UNIT_IN_METERS: f64 = 0.001;
fn value(&self) -> f64 { self.v }
fn new(value: f64) -> Mm {
Mm{ v: value }
}
}
struct Inch {
v: f64,
}
impl Length for Inch {
const UNIT_IN_METERS: f64 = 0.0254;
fn value(&self) -> f64 { self.v }
fn new(value: f64) -> Inch {
Inch{ v: value }
}
}
fn main() {
let foot = Inch::new(12f64);
let foot_in_mm: Mm = foot.convert_to();
println!("One foot in mm: {}", foot_in_mm.value());
}
Play link

Resources