Abstract over mutability with iterator item - rust

I've written a simple helper to loop over nibbles (4 bits) in an u8 slice. It uses an internal iterator over & u8 and essentially doubles the steps, where two steps both refer to the same underlying u8 but filter and shift the bits when viewed.
I created a mutable version as well (not pasted here) using Rc and RefCell, which requires an underlying iterator over &mut u8. However I would like the read-only version to also work with iterators that provide mutable access.
I've tried using I: 'a + Borrow<u8>, T: Iterator<Item = I> instead of the hard-coded &'a u8 and AsRef<u8> as well, but failed because with the inner byte becoming a non-reference, the borrowing occurs in my next() method where the borrowed values would escape their closure.
What would be required to allow my Nibbler to work with iterators that either iterate over &u8 or &mut u8?
pub enum Nibble<'a> {
MSB(&'a u8),
LSB(&'a u8),
}
impl Nibble<'_> {
pub fn from_u8(input: &u8) -> (Nibble, Nibble) {
let msb = Nibble::MSB(input);
let lsb = Nibble::LSB(input);
(msb, lsb)
}
pub fn get(&self) -> u8 {
match self {
Nibble::MSB(r) => (**r & 0b11110000) >> 4,
Nibble::LSB(r) => **r & 0b00001111,
}
}
}
pub struct Nibbler<'a, T> {
rest: Option<Nibble<'a>>,
inner: T,
}
impl<T> Nibbler<'_, T> {
pub fn new(inner: T) -> Self {
Nibbler { inner, rest: None }
}
}
impl<'a, T: Iterator<Item = &'a u8>> Iterator for Nibbler<'a, T> {
type Item = Nibble<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.rest.take().or_else(|| {
self.inner.next().map(|byte| {
let (msb, lsb) = Nibble::from_u8(byte);
self.rest = Some(msb);
lsb
})
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_nibble_get() {
let val = 0x79;
let (msb, lsb) = Nibble::from_u8(&val);
assert_eq!(msb.get(), 7);
assert_eq!(lsb.get(), 9);
}
#[test]
fn test_nibbler() {
let t = [0x12, 0x34, 0x56, 0x78];
for (i, nibble) in Nibbler::new(t.iter()).enumerate() {
match i {
0 => assert_eq!(nibble.get(), 2),
1 => assert_eq!(nibble.get(), 1),
2 => assert_eq!(nibble.get(), 4),
3 => assert_eq!(nibble.get(), 3),
4 => assert_eq!(nibble.get(), 6),
5 => assert_eq!(nibble.get(), 5),
6 => assert_eq!(nibble.get(), 8),
7 => assert_eq!(nibble.get(), 7),
_ => {}
}
}
}
// #[test]
// fn test_nibbler_mut() {
// let t = [0x12, 0x34, 0x56, 0x78];
// for (i, nibble) in Nibbler::new(t.iter_mut()).enumerate() {
// match i {
// 0 => assert_eq!(nibble.get(), 2),
// 1 => assert_eq!(nibble.get(), 1),
// 2 => assert_eq!(nibble.get(), 4),
// 3 => assert_eq!(nibble.get(), 3),
// 4 => assert_eq!(nibble.get(), 6),
// 5 => assert_eq!(nibble.get(), 5),
// 6 => assert_eq!(nibble.get(), 8),
// 7 => assert_eq!(nibble.get(), 7),
// _ => {}
// }
// }
// }
}
As requested by #chayim-friedman, here's my attempt with Borrow:
use std::borrow::Borrow;
impl<'a, I: Borrow<u8> + 'a, T: Iterator<Item = I>> Iterator for Nibbler<'a, T> {
type Item = Nibble<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.rest.take().or_else(|| {
self.inner.next().map(|byte| {
let (msb, lsb) = Nibble::from_u8(byte.borrow());
self.rest = Some(msb);
lsb
})
})
}
}
which errors with
error[E0515]: cannot return value referencing function parameter `byte`
--> src/utils/nibbler2.rs:42:17
|
40 | let (msb, lsb) = Nibble::from_u8(byte.borrow());
| ------------- `byte` is borrowed here
41 | self.rest = Some(msb);
42 | lsb
| ^^^ returns a value referencing data owned by the current function

After struggling with this for a while, I finally found the solution in this answer:
pub enum Nibble<'a> {
MSB(&'a u8),
LSB(&'a u8),
}
impl Nibble<'_> {
pub fn from_u8(input: &u8) -> (Nibble, Nibble) {
let msb = Nibble::MSB(input);
let lsb = Nibble::LSB(input);
(msb, lsb)
}
pub fn get(&self) -> u8 {
match self {
Nibble::MSB(r) => (**r & 0b11110000) >> 4,
Nibble::LSB(r) => **r & 0b00001111,
}
}
}
pub struct Nibbler<'a, T> {
rest: Option<Nibble<'a>>,
inner: T,
}
impl<T> Nibbler<'_, T> {
pub fn new(inner: T) -> Self {
Nibbler { inner, rest: None }
}
}
impl<'a, T> Iterator for Nibbler<'a, T>
where
T: Iterator,
<T as Iterator>::Item: IntoNibbleRef<'a>,
{
type Item = Nibble<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.rest.take().or_else(|| {
self.inner.next().map(|byte| {
let (msb, lsb) = Nibble::from_u8(byte.into_nibble_ref());
self.rest = Some(msb);
lsb
})
})
}
}
trait IntoNibbleRef<'a> {
fn into_nibble_ref(self) -> &'a u8;
}
impl<'a> IntoNibbleRef<'a> for &'a u8 {
fn into_nibble_ref(self) -> &'a u8 {
self
}
}
impl<'a> IntoNibbleRef<'a> for &'a mut u8 {
fn into_nibble_ref(self) -> &'a u8 {
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_nibble_get() {
let val = 0x79;
let (msb, lsb) = Nibble::from_u8(&val);
assert_eq!(msb.get(), 7);
assert_eq!(lsb.get(), 9);
}
#[test]
fn test_nibbler() {
let t = [0x12, 0x34, 0x56, 0x78];
for (i, nibble) in Nibbler::new(t.iter()).enumerate() {
match i {
0 => assert_eq!(nibble.get(), 2),
1 => assert_eq!(nibble.get(), 1),
2 => assert_eq!(nibble.get(), 4),
3 => assert_eq!(nibble.get(), 3),
4 => assert_eq!(nibble.get(), 6),
5 => assert_eq!(nibble.get(), 5),
6 => assert_eq!(nibble.get(), 8),
7 => assert_eq!(nibble.get(), 7),
_ => {}
}
}
}
#[test]
fn test_nibbler_mut() {
let mut t = [0x12, 0x34, 0x56, 0x78];
for (i, nibble) in Nibbler::new(t.iter_mut()).enumerate() {
match i {
0 => assert_eq!(nibble.get(), 2),
1 => assert_eq!(nibble.get(), 1),
2 => assert_eq!(nibble.get(), 4),
3 => assert_eq!(nibble.get(), 3),
4 => assert_eq!(nibble.get(), 6),
5 => assert_eq!(nibble.get(), 5),
6 => assert_eq!(nibble.get(), 8),
7 => assert_eq!(nibble.get(), 7),
_ => {}
}
}
}
}
You need to introduce another nested trait that can convert both &u8 and &mut u8 into &u8, here called IntoNibbleRef.
After a little more experimenting, I realized you can also implement such a trait generically:
impl<'a, T> Iterator for Nibbler<'a, T>
where
T: Iterator,
<T as Iterator>::Item: IntoImmutableRef<'a, u8>,
{
type Item = Nibble<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.rest.take().or_else(|| {
self.inner.next().map(|byte| {
let (msb, lsb) = Nibble::from_u8(byte.into_immutable_ref());
self.rest = Some(msb);
lsb
})
})
}
}
trait IntoImmutableRef<'a, T> {
fn into_immutable_ref(self) -> &'a T;
}
impl<'a, T> IntoImmutableRef<'a, T> for &'a T {
fn into_immutable_ref(self) -> &'a T {
self
}
}
impl<'a, T> IntoImmutableRef<'a, T> for &'a mut T {
fn into_immutable_ref(self) -> &'a T {
self
}
}

Related

How to zip two iterators of unequal length with a default?

I'm trying to zip two iterators of unequal length, it only returns when when there is value in both and ignores the rest in the longest iterator.
fn main() {
let num1 = vec![1, 2];
let num2 = vec![3];
for i in num1.iter().rev().zip(num2.iter().rev()) {
println!("{:?}", i);
}
}
This returns (2, 3). How do i make it return:
(2, 3)
(1, 0) // default is the 0 here.
Is there any other way to do it?
You could use the zip_longest provided by the itertools crate.
use itertools::{
Itertools,
EitherOrBoth::*,
};
fn main() {
let num1 = vec![1, 2];
let num2 = vec![3];
for pair in num1.iter().rev().zip_longest(num2.iter().rev()) {
match pair {
Both(l, r) => println!("({:?}, {:?})", l, r),
Left(l) => println!("({:?}, 0)", l),
Right(r) => println!("(0, {:?})", r),
}
}
}
Which would produce the following output:
(2, 3)
(1, 0)
Zip will stop as soon as one of iterators stops producing values. If you know which is the longest, you can pad the shorter one with your default value:
use std::iter;
fn main() {
let longer = vec![1, 2];
let shorter = vec![3];
for i in longer
.iter()
.rev()
.zip(shorter.iter().rev().chain(iter::repeat(&0)))
{
println!("{:?}", i);
}
}
If you don't know which is longest, you should use itertools, as Peter Varo suggests.
The key is to detect that one iterator is shorter then the other, you could do it before before in your case vector implement ExactSizeIterator but a general solution would be to have a custom .zip().
itertools already offer a general solution, .zip_longest():
use itertools::EitherOrBoth::{Both, Left, Right};
use itertools::Itertools;
fn main() {
let num1 = vec![1, 2];
let num2 = vec![3];
for i in num1
.iter()
.rev()
.zip_longest(num2.iter().rev())
.map(|x| match x {
Both(a, b) => (a, b),
Left(a) => (a, &0),
Right(b) => (&0, b),
})
{
println!("{:?}", i);
}
}
This require you write the closure everytime, if you need this feature a lot maybe implement a custom trait on iterator with .zip_default() where A and B implement Default:
use std::default::Default;
use std::iter::Fuse;
pub trait MyIterTools: Iterator {
fn zip_default<J>(self, other: J) -> ZipDefault<Self, J::IntoIter>
where
J: IntoIterator,
Self: Sized,
{
ZipDefault::new(self, other.into_iter())
}
}
#[derive(Clone, Debug)]
pub struct ZipDefault<I, J> {
i: Fuse<I>,
j: Fuse<J>,
}
impl<I, J> ZipDefault<I, J>
where
I: Iterator,
J: Iterator,
{
fn new(i: I, j: J) -> Self {
Self {
i: i.fuse(),
j: j.fuse(),
}
}
}
impl<T, U, A, B> Iterator for ZipDefault<T, U>
where
T: Iterator<Item = A>,
U: Iterator<Item = B>,
A: Default,
B: Default,
{
type Item = (A, B);
fn next(&mut self) -> Option<Self::Item> {
match (self.i.next(), self.j.next()) {
(Some(a), Some(b)) => Some((a, b)),
(Some(a), None) => Some((a, B::default())),
(None, Some(b)) => Some((A::default(), b)),
(None, None) => None,
}
}
}
impl<T: ?Sized> MyIterTools for T where T: Iterator {}
fn main() {
let num1 = vec![1, 2];
let num2 = vec![3];
for i in num1
.iter()
.copied()
.rev()
.zip_default(num2.iter().copied().rev())
{
println!("{:?}", i);
}
}
Using itertools we can delegate some logic:
use std::default::Default;
use itertools::Itertools;
use itertools::ZipLongest;
use itertools::EitherOrBoth::{Both, Left, Right};
pub trait MyIterTools: Iterator {
fn zip_default<J>(self, j: J) -> ZipDefault<Self, J::IntoIter>
where
Self: Sized,
J: IntoIterator,
{
ZipDefault::new(self, j.into_iter())
}
}
#[derive(Clone, Debug)]
pub struct ZipDefault<I, J> {
inner: ZipLongest<I, J>,
}
impl<I, J> ZipDefault<I, J>
where
I: Iterator,
J: Iterator,
{
fn new(i: I, j: J) -> Self {
Self {
inner: i.zip_longest(j),
}
}
}
impl<T, U, A, B> Iterator for ZipDefault<T, U>
where
T: Iterator<Item = A>,
U: Iterator<Item = B>,
A: Default,
B: Default,
{
type Item = (A, B);
fn next(&mut self) -> Option<Self::Item> {
match self.inner.next()? {
Both(a, b) => Some((a, b)),
Left(a) => Some((a, B::default())),
Right(b) => Some((A::default(), b)),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T: ?Sized> MyIterTools for T where T: Iterator {}
fn main() {
let num1 = vec![1, 2];
let num2 = vec![3];
for i in num1
.iter()
.copied()
.rev()
.zip_default(num2.iter().copied().rev())
{
println!("{:?}", i);
}
}
I saw this neat trick in other guy code in leetcode solution. If you have access to length, you can swap iterators, making iter1 the longest.
fn main() {
let num1 = vec![1, 2];
let num2 = vec![3];
let mut iter1 = num1.iter();
let mut iter2 = num2.iter();
if iter1.len() < iter2.len(){
std::mem::swap(&mut iter1, &mut iter2);
} // now iter1 is the largest
for i in iter1.rev().zip(iter2.rev().chain(std::iter::repeat(&0))) {
println!("{:?}", i);
}
}
If you can get the length of the iterators, as is in this case, a quick and dirty way could be:
use std::iter::repeat;
fn main() {
let a = vec![1, 2, 3];
let b = vec![4, 5, 6, 7];
for i in a
.iter()
.rev()
.chain(repeat(&0).take(b.len().saturating_sub(a.len())))
.zip(
b.iter()
.rev()
.chain(repeat(&0).take(a.len().saturating_sub(b.len()))),
)
{
println!("{:?}", i);
}
}
You can also implement a trait containing a zip_default() using this approach:
pub trait MyIterTools<X: Default + Clone>: ExactSizeIterator<Item = X> {
fn zip_default<J, Y>(self, j: J) -> ZipDefault<Self, J::IntoIter, X, Y>
where
Self: Sized,
J: IntoIterator<Item = Y>,
J::IntoIter: ExactSizeIterator,
Y: Default + Clone,
{
ZipDefault::new(self, j.into_iter())
}
}
#[derive(Clone, Debug)]
pub struct ZipDefault<
I: ExactSizeIterator<Item = X>,
J: ExactSizeIterator<Item = Y>,
X: Default + Clone,
Y: Default + Clone,
> {
inner: Zip<Chain<I, Take<Repeat<X>>>, Chain<J, Take<Repeat<Y>>>>,
}
impl<
I: ExactSizeIterator<Item = X>,
J: ExactSizeIterator<Item = Y>,
X: Default + Clone,
Y: Default + Clone,
> ZipDefault<I, J, X, Y>
{
fn new(a: I, b: J) -> Self {
let a_len = a.len();
let b_len = b.len();
Self {
inner: a
.chain(repeat(X::default()).take(b_len.saturating_sub(a_len)))
.zip(b.chain(repeat(Y::default()).take(a_len.saturating_sub(b_len)))),
}
}
}
impl<
I: ExactSizeIterator<Item = X>,
J: ExactSizeIterator<Item = Y>,
X: Default + Clone,
Y: Default + Clone,
> Iterator for ZipDefault<I, J, X, Y>
{
type Item = (X, Y);
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<T: ExactSizeIterator<Item = X>, X: Default + Clone> MyIterTools<X> for T {}
fn main() {
let a = vec![1, 2, 3];
let b = vec![4, 5, 6, 7];
a.into_iter()
.zip_default(b.into_iter())
.for_each(|i| println!("{:?}", i));
}

How to convert a linked list of Option<Box<ListNode>> to a Vec<i32>?

I want to convert the following Option<Box<ListNode>> type to Vec<i32> type:
fn main() {
Some(ListNode {
val: 3,
next: Some(ListNode {
val: 4,
next: Some(ListNode { val: 2, next: None }),
}),
})
}
I want to implement the list_to_vec function:
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>,
}
impl ListNode {
pub fn new(val: i32) -> Self {
ListNode { next: None, val }
}
pub fn vec_to_list(mut value: Vec<i32>) -> Option<Box<ListNode>> {
match value.pop() {
Some(x) => Some(Box::new(ListNode {
val: x,
next: ListNode::vec_to_list(value),
})),
None => None,
}
}
pub fn list_to_vec(mut value: &Option<ListNode>) -> Vec<i32> {
//????????????????????????????
}
}
Desired output
[3, 4, 2]
I have tried:
pub fn list_to_vec(mut value: &Option<ListNode>) -> Vec<i32> {
let mut v = vec![];
match value {
Some(x) => {
&v.push(x.val);
Self::list_to_vec(x.next)
}
None => v,
}
}
let h = ListNode::vec_to_list(vec![2, 4, 3]);
println!("{:#?}", ListNode::list_to_vec(&h));
it has an error:
error[E0308]: mismatched types
--> src\main.rs:27:56
|
27 | Some(x) => {&v.push(x.val);Self::list_to_vec(x.next)},
| ^^^^^^ expected reference, found enum `std::option::Option`
|
= note: expected type `&std::option::Option<ListNode>`
found type `std::option::Option<std::boxed::Box<ListNode>>`
error[E0308]: mismatched types
--> src\main.rs:74:40
|
74 | println!("{:#?}",ListNode::list_to_vec(&h));
| ^^ expected struct `ListNode`, found struct `std::boxed::Box`
|
= note: expected type `&std::option::Option<ListNode>`
found type `&std::option::Option<std::boxed::Box<ListNode>>`
You will blow your stack if you don't do tail recursive function, your vec_to_list() can't handle a medium vector size. For your list_to_vec() you could just implement Iterator and collect it, fast and dirty example:
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>,
}
pub struct ListIter<'a> {
iter: &'a Option<Box<ListNode>>,
}
impl<'a> Iterator for ListIter<'a> {
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if let Some(cur) = self.iter {
self.iter = &cur.next;
Some(cur.val)
} else {
None
}
}
}
impl ListNode {
pub fn new(val: i32) -> Self {
ListNode { next: None, val }
}
pub fn vec_to_list<'a>(
value: impl IntoIterator<IntoIter = impl DoubleEndedIterator<Item = &'a i32>, Item = &'a i32>,
) -> Option<Box<ListNode>> {
Self::vec_to_list_aux(value.into_iter().rev().copied(), None)
}
fn vec_to_list_aux(
value: impl Iterator<Item = i32>,
accu: Option<Box<ListNode>>,
) -> Option<Box<ListNode>> {
let mut value = value;
match value.next() {
Some(x) => {
Self::vec_to_list_aux(value, Some(Box::new(ListNode { val: x, next: accu })))
}
None => accu,
}
}
pub fn list_to_vec(list: &Option<Box<ListNode>>) -> Vec<i32> {
Self::iter(list).collect()
}
fn iter(list: &Option<Box<ListNode>>) -> ListIter {
ListIter { iter: &list }
}
}
fn main() {
let list = ListNode::vec_to_list(&[3, 4, 2]);
println!("{:#?}", list);
println!("{:?}", ListNode::list_to_vec(&list));
}
I resolved it.
pub fn list_to_vec(mut value: Option<Box<ListNode>>, mut v_cup: Vec<i32>) -> Vec<i32> {
match value {
Some(x) => {
v_cup.push(x.val);
Self::list_to_vec(x.next, v_cup)
}
None => v_cup,
}
}
let h = ListNode::vec_to_list(vec![2, 4, 3]);
let v_cup = vec![];
println!("{:?}", ListNode::list_to_vec(h, v_cup));
A recursive solution isn't needed here, and is likely to not be as efficient as the iterative solution.
Taking ownership:
pub fn list_to_vec(mut value: Option<Box<ListNode>>) -> Vec<i32> {
let mut v = Vec::new();
while let Some(n) = value {
v.push(n.val);
value = n.next;
}
v
}
By reference:
pub fn list_to_vec(mut value: &Option<Box<ListNode>>) -> Vec<i32> {
let mut v = Vec::new();
while let Some(n) = value {
v.push(n.val);
value = &n.next;
}
v
}

Why can I not dereference or add a generic type even though I'm passing in a type that can be dereferenced and added?

I have some problems with a generic implementation of a method:
use std::collections::BTreeMap;
use global::entity::EntityId;
struct simple_system<T> {
list_sum: BTreeMap<EntityId, T>,
list_com: BTreeMap<EntityId, Vec<T>>,
}
impl<T> simple_system<T> {
pub fn new() -> simple_system<T> {
simple_system {
list_sum: BTreeMap::new(),
list_com: BTreeMap::new(),
}
}
pub fn addComponent(&mut self, id: EntityId, comp: T) {
self.list_com.entry(id).or_insert_with(Vec::new).push(comp);
match self.list_sum.get_mut(&id) {
Some(v) => *v = *v + *comp,
None => self.list_sum.insert(id, comp),
}
}
}
with the following errors.
error[E0614]: type `T` cannot be dereferenced
--> src/main.rs:20:34
|
20 | Some(v) => *v = *v + *comp,
| ^^^^^
error[E0369]: binary operation `+` cannot be applied to type `T`
--> src/main.rs:20:29
|
20 | Some(v) => *v = *v + *comp,
| ^^^^^^^^^^
|
= note: an implementation of `std::ops::Add` might be missing for `T`
I don't know what I have to change to get it to work. I use it with u32 type so it should have an + operator.
The Rust generics systems doesn't work the way C++ templates do: in C++ the compiler doesn't check whether the code actually compiles with any type in advance.
Rust makes sure the function compiles with any type that fulfills the listed requirements (called trait bounds). The compiler already told you what is missing: std::ops::Add might be missing for T, so ask for it:
impl<T: Add<Output = T>> simple_system<T> { /* … */ }
This will not fix everything; your code has other issues as well.
And here the Solution:
At first you should write a working non generic (c++ template) version and then evolve it to a generic version.
use std::collections::BTreeMap;
#[derive(Debug)]
struct SumUpSystem {
list_sum: BTreeMap<u64, i32 >,
list_com: BTreeMap<u64, Vec<i32> >
}
impl SumUpSystem {
pub fn new() -> SumUpSystem {
SumUpSystem {
list_sum: BTreeMap::new(),
list_com: BTreeMap::new()
}
}
pub fn add_component(&mut self, id: u64, comp: i32) {
self.list_com.entry(id).or_insert_with(Vec::new).push(comp);
let mut insert = false;
match self.list_sum.get_mut(&id) {
Some(x) => *x = *x + comp,
None => insert = true
}
if (insert) {
self.list_sum.insert(id, comp);
}
}
pub fn sum(& self, id: u64) -> i32 {
if let Some(x) = self.list_sum.get(&id) {
*x
} else {
panic!("Invalid id: Not in system!");
}
}
}
#[cfg(test)]
mod test {
use super::*;
macro_rules! init_test {
($v:ident) => (let mut $v : SumUpSystem = SumUpSystem::new(););
}
#[test]
fn add_component() {
init_test!(s);
s.add_component(1, 13);
assert_eq!(s.sum(1), 13);
s.add_component(1, 26);
assert_eq!(s.sum(1), 13 + 26);
}
}
The generic (c++ template). You should read the Trait section of the Rust Documentation to understand how/why it works.
use std::collections::BTreeMap;
use std::ops::Add;
#[derive(Debug)]
struct SumUpSystem<T> {
list_sum: BTreeMap<u64, T >,
list_com: BTreeMap<u64, Vec<T> >
}
impl <T: Add<Output=T> + Clone> SumUpSystem<T> {
pub fn new() -> SumUpSystem<T> {
SumUpSystem {
list_sum: BTreeMap::new(),
list_com: BTreeMap::new()
}
}
pub fn add_component(&mut self, id: u64, comp: &T) {
self.list_com.entry(id).or_insert_with(Vec::new).push(comp.clone());
let mut insert = false;
match self.list_sum.get_mut(&id) {
Some(x) => *x = x.clone() + comp.clone(),
None => insert = true
}
if insert {
self.list_sum.insert(id, comp.clone());
}
}
pub fn sum(& self, id: u64) -> T {
if let Some(x) = self.list_sum.get(&id) {
x.clone()
} else {
panic!("Invalid id: Not in system!");
}
}
}
#[cfg(test)]
mod test {
use super::*;
macro_rules! init_test {
($v:ident) => (let mut $v : SumUpSystem<i32> = SumUpSystem::new(););
}
#[test]
fn add_component() {
init_test!(s);
s.add_component(1, &13i32);
assert_eq!(s.sum(1), 13i32);
s.add_component(1, &26i32);
assert_eq!(s.sum(1), 39i32);
}
}

Extend Iterator with a "mean" method

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.

Is there a way to perform an index access to an instance of a struct?

Is there a way to perform an index access to an instance of a struct like this:
struct MyStruct {
// ...
}
impl MyStruct {
// ...
}
fn main() {
let s = MyStruct::new();
s["something"] = 533; // This is what I need
}
You can use the Index and IndexMut traits.
use std::ops::{Index, IndexMut};
struct Foo {
x: i32,
y: i32,
}
impl Index<&'_ str> for Foo {
type Output = i32;
fn index(&self, s: &str) -> &i32 {
match s {
"x" => &self.x,
"y" => &self.y,
_ => panic!("unknown field: {}", s),
}
}
}
impl IndexMut<&'_ str> for Foo {
fn index_mut(&mut self, s: &str) -> &mut i32 {
match s {
"x" => &mut self.x,
"y" => &mut self.y,
_ => panic!("unknown field: {}", s),
}
}
}
fn main() {
let mut foo = Foo { x: 0, y: 0 };
foo["y"] += 2;
println!("x: {}", foo["x"]);
println!("y: {}", foo["y"]);
}
It prints:
x: 0
y: 2
You want to use the Index trait (and its pair IndexMut):
use std::ops::Index;
#[derive(Copy, Clone)]
struct Foo;
struct Bar;
impl Index<Bar> for Foo {
type Output = Foo;
fn index<'a>(&'a self, _index: Bar) -> &'a Foo {
println!("Indexing!");
self
}
}
fn main() {
Foo[Bar];
}

Resources