Error while calculating Getting average of chunks [duplicate] - rust

This code works:
fn main() {
let a: i32 = (1i32..10).sum();
let b = a.pow(2);
}
If I remove the i32 type from a, then I get this error:
rustc 1.13.0 (2c6933acc 2016-11-07)
error: the type of this value must be known in this context
--> <anon>:3:13
|
5 | let b = a.pow(2);
| ^^^^^^^^
Run the example
I would have expected that Rust turns (1i32..10) into an i32 iterator and then sum() knows to return an i32. What am I missing?

The way sum is defined, the return value is open-ended; more than one type can implement the trait Sum<i32>. Here's an example where different types for a are used, both of which compile:
#[derive(Clone, Copy)]
struct Summer {
s: isize,
}
impl Summer {
fn pow(&self, p: isize) {
println!("pow({})", p);
}
}
impl std::iter::Sum<i32> for Summer {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = i32>,
{
let mut result = 0isize;
for v in iter {
result += v as isize;
}
Summer { s: result }
}
}
fn main() {
let a1: i32 = (1i32..10).sum();
let a2: Summer = (1i32..10).sum();
let b1 = a1.pow(2);
let b2 = a2.pow(2);
}
Playground
Since both result types are possible, the type cannot be inferred and must be explicitly specified, either by a turbofish (sum::<X>()) or as the result of the expression (let x: X = ...sum();).

and then sum() knows to return an i32
This is the key missing point. While the "input" type is already known (it has to be something that implements Iterator in order for sum to even be available), the "output" type is very flexible.
Check out Iterator::sum:
fn sum<S>(self) -> S
where
S: Sum<Self::Item>,
It returns a generic type S which has to implement Sum. S does not have to match Self::Item. Therefore, the compiler requires you to specify what
type to sum into.
Why is this useful? Check out these two sample implementations from the standard library:
impl Sum<i8> for i8
impl<'a> Sum<&'a i8> for i8
That's right! You can sum up an iterator of u8 or an iterator of &u8! If we didn't have this, then this code wouldn't work:
fn main() {
let a: i32 = (0..5).sum();
let b: i32 = [0, 1, 2, 3, 4].iter().sum();
assert_eq!(a, b);
}
As bluss points out, we could accomplish this by having an associated type which would tie u8 -> u8 and &'a u8 -> u8.
If we only had an associated type though, then the target sum type would always be fixed, and we'd lose flexibility. See When is it appropriate to use an associated type versus a generic type? for more details.
As an example, we can also implement Sum<u8> for our own types. Here, we sum up u8s, but increase the size of the type we are summing, as it's likely the sum would exceed a u8. This implementation is in addition to the existing implementations from the standard library:
#[derive(Debug, Copy, Clone)]
struct Points(i32);
impl std::iter::Sum<u8> for Points {
fn sum<I>(iter: I) -> Points
where
I: Iterator<Item = u8>,
{
let mut pts = Points(0);
for v in iter {
pts.0 += v as i32;
}
pts
}
}
fn main() {
let total: Points = (0u8..42u8).sum();
println!("{:?}", total);
}

Related

Understanding type inference in Rust [duplicate]

This code works:
fn main() {
let a: i32 = (1i32..10).sum();
let b = a.pow(2);
}
If I remove the i32 type from a, then I get this error:
rustc 1.13.0 (2c6933acc 2016-11-07)
error: the type of this value must be known in this context
--> <anon>:3:13
|
5 | let b = a.pow(2);
| ^^^^^^^^
Run the example
I would have expected that Rust turns (1i32..10) into an i32 iterator and then sum() knows to return an i32. What am I missing?
The way sum is defined, the return value is open-ended; more than one type can implement the trait Sum<i32>. Here's an example where different types for a are used, both of which compile:
#[derive(Clone, Copy)]
struct Summer {
s: isize,
}
impl Summer {
fn pow(&self, p: isize) {
println!("pow({})", p);
}
}
impl std::iter::Sum<i32> for Summer {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = i32>,
{
let mut result = 0isize;
for v in iter {
result += v as isize;
}
Summer { s: result }
}
}
fn main() {
let a1: i32 = (1i32..10).sum();
let a2: Summer = (1i32..10).sum();
let b1 = a1.pow(2);
let b2 = a2.pow(2);
}
Playground
Since both result types are possible, the type cannot be inferred and must be explicitly specified, either by a turbofish (sum::<X>()) or as the result of the expression (let x: X = ...sum();).
and then sum() knows to return an i32
This is the key missing point. While the "input" type is already known (it has to be something that implements Iterator in order for sum to even be available), the "output" type is very flexible.
Check out Iterator::sum:
fn sum<S>(self) -> S
where
S: Sum<Self::Item>,
It returns a generic type S which has to implement Sum. S does not have to match Self::Item. Therefore, the compiler requires you to specify what
type to sum into.
Why is this useful? Check out these two sample implementations from the standard library:
impl Sum<i8> for i8
impl<'a> Sum<&'a i8> for i8
That's right! You can sum up an iterator of u8 or an iterator of &u8! If we didn't have this, then this code wouldn't work:
fn main() {
let a: i32 = (0..5).sum();
let b: i32 = [0, 1, 2, 3, 4].iter().sum();
assert_eq!(a, b);
}
As bluss points out, we could accomplish this by having an associated type which would tie u8 -> u8 and &'a u8 -> u8.
If we only had an associated type though, then the target sum type would always be fixed, and we'd lose flexibility. See When is it appropriate to use an associated type versus a generic type? for more details.
As an example, we can also implement Sum<u8> for our own types. Here, we sum up u8s, but increase the size of the type we are summing, as it's likely the sum would exceed a u8. This implementation is in addition to the existing implementations from the standard library:
#[derive(Debug, Copy, Clone)]
struct Points(i32);
impl std::iter::Sum<u8> for Points {
fn sum<I>(iter: I) -> Points
where
I: Iterator<Item = u8>,
{
let mut pts = Points(0);
for v in iter {
pts.0 += v as i32;
}
pts
}
}
fn main() {
let total: Points = (0u8..42u8).sum();
println!("{:?}", total);
}

How to use recursive associated types in functions?

I am trying to write a function that can descent into any kind of Value and inform a Delegate about the similarities it observes. The idea is to make this work across all kinds of Json/Yaml/YouNameIt values, generically.
Here is an MVCE to trigger the issue (playground link):
pub trait Value: PartialEq<Self> {
type Item;
type Key;
fn items<'a>(&'a self) -> Option<Box<Iterator<Item = (Self::Key, &'a Self::Item)> + 'a>>;
}
pub trait Delegate<'a, V> {
fn something(&mut self, _v: &'a V) {}
}
pub fn diff<'a, V, D>(l: &'a V, d: &'a mut D)
where V: Value,
<V as Value>::Item: Value,
D: Delegate<'a, V>
{
d.something(l);
let v = l.items().unwrap().next().unwrap();
d.something(v.1);
}
struct Recorder;
impl<'a, V> Delegate<'a, V> for Recorder {}
#[derive(PartialEq)]
struct RecursiveValue;
impl Value for RecursiveValue {
type Key = usize;
type Item = RecursiveValue;
fn items<'a>(&'a self) -> Option<Box<Iterator<Item = (Self::Key, &'a Self::Item)> + 'a>> {
None
}
}
fn main() {
let v = RecursiveValue;
let mut r = Recorder;
diff(&v, &mut r);
}
When attempting to compile the code, the following error is produced:
error[E0308]: mismatched types
--> <anon>:19:17
|
19 | d.something(v.1);
| ^^^ expected type parameter, found associated type
|
= note: expected type `&'a V`
= note: found type `&<V as Value>::Item`
I'm trying to say that the associated Item type is of type V too. Is there a way to make such an algorithm work generically?
The answer lies at the very bottom of the Associated Types chapter of the Rust Book.
When using a generic type in a bound, as in V: Value, it is possible to constrain one or several of its associated types to specific types by using the Generic<AssociatedType = SpecificType> syntax.
In your case, it means constraining V to Value<Item = V>. This should also obsolete any reason to further constrain V::Item since the bounds to V are naturally available.
I do encourage you to read the book to help you learn Rust, or at least skim it to know what's available there and be able to refer to it when you have a difficulty.
Here's a further reduced example:
pub trait Value {
type Item;
fn items(&self) -> &Self::Item;
}
pub trait Delegate<V> {
fn something(&mut self, v: &V);
}
pub fn diff<V, D>(l: &V, d: &mut D)
where V: Value,
V::Item: Value,
D: Delegate<V>
{
let v = l.items();
d.something(v);
}
fn main() {}
The important thing to focus on are the restrictions on the generics of diff:
pub fn diff<V, D>(l: &V, d: &mut D)
where V: Value,
V::Item: Value,
D: Delegate<V>
In words, this says:
V can be any type so long as it implements the Value trait.
V::Item can be any type so long as it implements the Value trait.
D can be any type so long as it implements the Delegate<V> trait.
Nowhere in that list of requirements was listed "V and V::Item must be the same". In fact, it's a feature that they are not required to be the same.
In this reduction, another solution would be to say D: Delegate<V::Item>. However, that wouldn't apply to the slightly larger reproduction:
pub fn diff<V, D>(l: &V, d: &mut D)
where V: Value,
V::Item: Value,
D: Delegate<V::Item>
{
d.something(l);
let v = l.items();
d.something(v);
}
As Matthieu M. has pointed out, you want to specify the associated type of the trait:
pub fn diff<V, D>(l: &V, d: &mut D)
where V: Value<Item = V>,
D: Delegate<V>
For further reading, check out Requiring implementation of Mul in generic function.

Generic Type Mismatch using Trait in Rust

I am doing a matrix addition using traits. I am stuck by the generic type mismatch. My code is as following:
use std::{ops, fmt};
#[derive(PartialEq, Debug)]
pub struct Matrix<T> {
data: Vec<T>,
row: usize,
col: usize,
}
impl<T: Copy> Matrix<T> {
/// Creates a new matrix of `row` rows and `col` columns, and initializes
/// the matrix with the elements in `values` in row-major order.
pub fn new(row: usize, col: usize, values: &[T]) -> Matrix<T> {
Matrix {
data: values.to_vec(), // make copy and convert &[T] to vector type
row: row,
col: col,
}
}
}
impl<T: ops::Add<Output = T> + Copy> ops::Add for Matrix<T> {
type Output = Self;
/// Returns the sum of `self` and `rhs`. If `self.row != rhs.row || self.col != rhs.col`, panic.
fn add(self, rhs: Self) -> Self::Output {
assert!(self.col == rhs.col);
assert!(self.row == rhs.row);
let mut newdata = Vec::new(); // make a new vector to store result
let mut sum: i32; // temp variable to record each addition
for num1 in self.data.iter() {
for num2 in rhs.data.iter() {
sum = *num1 + *num2;
newdata.push(sum)
}
}
Matrix {
data: newdata, // finally, return addition result using new_data
row: self.row,
col: self.col,
}
}
}
fn main() {
let x = Matrix::new(2, 3, &[-6, -5, 0, 1, 2, 3]);
let y = Matrix::new(2, 3, &[0, 1, 0, 0, 0, 0]);
// z = x + y;
}
Compiling the program, I got two errors about type mismatch:
error[E0308]: mismatched types
--> src/main.rs:36:23
|
36 | sum = *num1 + *num2;
| ^^^^^^^^^^^^^ expected i32, found type parameter
|
= note: expected type `i32`
= note: found type `T`
error[E0308]: mismatched types
--> src/main.rs:41:9
|
41 | Matrix {
| ^ expected type parameter, found i32
|
= note: expected type `Matrix<T>`
= note: found type `Matrix<i32>`
My thoughts:
num1 would deref the vector and get a integer type, that's why I use a sum to record the result.
I am trying to return a Matrix type value at the end of the function.
What is going wrong?
This is the entire knowledge of your types that the code can rely on inside of the method:
impl<T: ops::Add<Output = T> + Copy> ops::Add for Matrix<T> {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
// ...
}
}
Based on that, how would it be possible to make this assumption?
num1 would deref the vector and get a integer type
There is no way to know what concrete type T will be!
Beyond that, even if it were some integer type, how would it be possible to assume that summing into an i32 is acceptable? What if T were a i64?
The solution is to remove any assumptions and let the compiler do its job. Remove the type annotation from sum and the code compiles. I find it good practice to always allow the compiler to infer my types when possible.
See also:
Requiring implementation of Mul in generic function
"Expected type parameter" error in the constructor of a generic struct

Is it possible to pass an object method as argument to a function and bind it to the object?

Is it possible to make a bind to object method? For example, I have a vector and a lot of functions which do something if some item exists in the vector. I would implement it as follows:
fn perform_if_exists(item: u8, vector: &Vec<u8>, func: fn(usize)) {
let idx = vector.iter().position(|i| *i == item );
match idx {
Some(i) => func(i),
None => {},
}
}
fn main() {
let v: Vec<u8> = vec![1, 2, 3];
perform_if_exists(1, &v, Vec<_>::remove);
}
but it gives a lot of errors. I think they are reasonable but it's because I don't understand how to put vector's method as argument to a function.
Is it possible
Sure it is. You have to fix the multiple cascading errors first:
Invalid syntax: Vec<_>::remove isn't valid.
Incompatible argument types: Vec::remove modifies a Vec, so you have to pass in a Vec somehow.
Mutability: Vec::remove modifies a Vec, so you have to declare that the function is allowed to do so.
Vec::remove returns the removed value, so you have to allow the function to return a value, even if it's thrown away.
fn perform_if_exists<F, R>(item: u8, vector: &mut Vec<u8>, func: F)
where
F: Fn(&mut Vec<u8>, usize) -> R,
{
let idx = vector.iter().position(|i| *i == item);
if let Some(i) = idx {
func(vector, i);
}
}
fn main() {
let mut v = vec![1, 2, 3];
perform_if_exists(1, &mut v, Vec::remove);
println!("{:?}", v);
}
I switched to a generic as that's generally how you will accept closures. A function pointer is fine but more restrictive.
A method in Rust is nothing more than a function, which also takes a first self parameter. The method Vec::remove takes two arguments: &mut self and index: usize. The self parameter is always of type Self, which is Vec<u8> in this case. The complete type of Vec::<u8>::remove is: fn(&mut Vec<u8>, usize) -> u8 (yes it also returns the removed element).
After changing the type in your code (+ a few minor mistakes), it works:
// vvv-- has to be mutable
fn perform_if_exists(item: u8, vector: &mut Vec<u8>, func: fn(&mut Vec<u8>, usize) -> u8) {
let idx = vector.iter().position(|i| *i == item );
match idx {
Some(i) => {
func(vector, i);
},
None => {},
}
}
fn main() {
let mut v: Vec<u8> = vec![1, 2, 3];
perform_if_exists(1, &mut v, Vec::remove);
}
But fn(...) -> ... types are raw pointer types and just work for ordinary functions. Often you also want to enable the user to pass anything that is "callable", like closures. There are traits exactly for that purpose: Fn(...) -> ....
Let me propose another solution:
fn perform_if_exists<T, F, R>(item: T, vector: &mut Vec<T>, func: F) -> Option<R>
where F: FnOnce(&mut Vec<T>, usize) -> R,
T: PartialEq
{
let idx = vector.iter().position(|i| *i == item );
idx.map(|i| func(vector, i))
}
This solution is far more generic as it allows arbitrary item types, arbitrary "callable" types and returns the value that is returned by the given function. Note that the main function didn't change; the solution is more generic, but all old uses still work.

How can I use `index_mut` to get a mutable reference?

Even when I implement IndexMut for my struct, I cannot get a mutable reference to an element of structure inner vector.
use std::ops::{Index, IndexMut};
struct Test<T> {
data: Vec<T>,
}
impl<T> Index<usize> for Test<T> {
type Output = T;
fn index<'a>(&'a self, idx: usize) -> &'a T {
return &self.data[idx];
}
}
impl<T> IndexMut<usize> for Test<T> {
fn index_mut<'a>(&'a mut self, idx: usize) -> &'a mut T {
// even here I cannot get mutable reference to self.data[idx]
return self.data.index_mut(idx);
}
}
fn main() {
let mut a: Test<i32> = Test { data: Vec::new() };
a.data.push(1);
a.data.push(2);
a.data.push(3);
let mut b = a[1];
b = 10;
// will print `[1, 2, 3]` instead of [1, 10, 3]
println!("[{}, {}, {}]", a.data[0], a.data[1], a.data[2]);
}
How can I use index_mut to get a mutable reference? Is it possible?
You're almost there. Change this:
let mut b = a[1];
b = 10;
to this:
let b = &mut a[1];
*b = 10;
Indexing syntax returns the value itself, not a reference to it. Your code extracts one i32 from your vector and modifies the variable - naturally, it does not affect the vector itself. In order to obtain a reference through the index, you need to write it explicitly.
This is fairly natural: when you use indexing to access elements of a slice or an array, you get the values of the elements, not references to them, and in order to get a reference you need to write it explicitly.

Resources