This question arises from my use (in a toy project to learn Rust) of cartesian_product from itertools together with into_par_iter from Rayon. My question is less about this particular code and more a question about reading rustc error messages, and the Rust library documentation.
This works as expected:
fn main() {
let it = 0..15;
it.into_par_iter().for_each(|x| println!("{:?}", x));
}
But the code below fails to compile with the error indicated. The documentation for the Product returned by cartesian_product includes an implementation of Iterator, so I would have expected the into_par_iter method call to type check, but such is not the case.
Here's the failing code and the resulting error message:
fn main() {
let it = (0..15).cartesian_product(0..8);
it.into_par_iter().for_each(|x| println!("{:?}", x));
}
Compiling iters v0.1.0 (D:\rust\iters)
error[E0599]: no method named `into_par_iter` found for struct `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>` in the current scope
--> src\main.rs:8:8
|
8 | it.into_par_iter().for_each(|x| println!("{:?}", x));
| ^^^^^^^^^^^^^ method not found in `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>`
|
::: D:\rust\dot.cargo\registry\src\github.com-1ecc6299db9ec823\itertools-0.9.0\src\adaptors\mod.rs:288:1
|
288 | / pub struct Product<I, J>
289 | | where I: Iterator
290 | | {
291 | | a: I,
... |
294 | | b_orig: J,
295 | | }
| | -
| | |
| |_doesn't satisfy `_: rayon::iter::IntoParallelIterator`
| doesn't satisfy `_: rayon::iter::ParallelIterator`
|
= note: the method `into_par_iter` exists but the following trait bounds were not satisfied:
`itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::ParallelIterator`
which is required by `itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::IntoParallelIterator`
`&itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::ParallelIterator`
which is required by `&itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::IntoParallelIterator`
`&mut itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::ParallelIterator`
which is required by `&mut itertools::adaptors::Product<std::ops::Range<{integer}>, std::ops::Range<{integer}>>: rayon::iter::IntoParallelIterator`
itertools::Itertools::cartesian_product returns a value of type itertools::Product, which implements std's Iterator.
However, Rayon can't just work with any type that implements Iterator - it must also implement rayon::ParallelIterator. Rayon happens to provide implementations of ParallelIterator for most std iterators, but it can't implement them for structs in another crate (like itertools) without depending on that crate. Similarly, itertools couldn't implement rayon::ParallelIterator for its types without depending on rayon.
Instead, you can duplicate the functionality of Itertools::cartesian_product yourself using Rayon's API:
use rayon::iter::{ParallelIterator, IntoParallelIterator};
fn main() {
(0..15).into_par_iter()
.flat_map(|i| (0..8).into_par_iter().map(move |j| (i, j)))
.for_each(|x| println!("{:?}", x));
}
Alternatively, you can start with an iterator of length (15 * 8) and then use division and remainder to break it down into tuples:
use rayon::iter::{ParallelIterator, IntoParallelIterator};
fn main() {
let it = (0 .. 15 * 8).into_par_iter().map(|x| (x / 8, x % 8));
it.for_each(|x| println!("{:?}", x));
}
Related
I am trying to figure out, why the sample code does not work?
This is in my toml file:
polars = "*"
This is the sample from Polars Eager cookbook:
use polars::prelude::*;
fn main() {
let s = Series::new("a", &[1, 2, 3]);
let ca = UInt32Chunked::new("b", &[Some(3), None, Some(1)]);
println!("{:?}", s.eq(2));
println!("{:?}", ca.eq(2));
}
It looks like the "eq" function is not properly overloaded?! I am getting the following errors:
error[E0308]: mismatched types
--> src\main.rs:7:27
|
7 | println!("{:?}", s.eq(2));
| -- ^ expected `&polars::prelude::Series`, found integer
| |
| arguments to this function are incorrect
|
note: associated function defined here
--> C:\Users\rnio\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\cmp.rs:228:8
|
228 | fn eq(&self, other: &Rhs) -> bool;
| ^^
error[E0599]: `ChunkedArray<UInt32Type>` is not an iterator
--> src\main.rs:9:25
|
9 | println!("{:?}", ca.eq(2));
| ^^ `ChunkedArray<UInt32Type>` is not an iterator
|
::: C:\Users\rnio\.cargo\registry\src\github.com-1ecc6299db9ec823\polars-core-0.22.7\src\chunked_array\mod.rs:143:1
|
143 | pub struct ChunkedArray<T> {
| -------------------------- doesn't satisfy `ChunkedArray<UInt32Type>: Iterator`
|
= note: the following trait bounds were not satisfied:
`ChunkedArray<UInt32Type>: Iterator`
which is required by `&mut ChunkedArray<UInt32Type>: Iterator`
Thanks to #isaactfa ... the current workaround is to convert the Series to a ChunckedArray before comparisons.
Here is a working code:
use polars::prelude::*;
fn main() {
let s = Series::new("a", &[1, 2, 3]);
let ca = UInt32Chunked::new("b", &[Some(3), None, Some(1)]);
println!("{:?}", s.i32().unwrap().equal(2));
println!("{:?}", ca.equal(3));
}
I'm working on some bit manipulation code that converts primitive integers into a newtype called struct Bits(Vec<bool>) where the bools in the vec each represent a single bit. I implemented the From trait to convert from Bits back to usize and it worked perfectly. I changed the same implementation of From to convert from Bits back to u8 and it complains about u8 not satisfying my trait bounds for things like BitAnd even though u8 definitely does have an implementation for BitAnd. In fact, u8 and usize implement BitAnd via the exact same call to a macro in Rust's library. The trait bounds in question are from a blanket implementation from my BitMan trait. What am I not understanding that makes the usize work fine but the u8 not even compile?
The full error and notes I get is:
error[E0599]: the method `set_bit` exists for type `u8`, but its trait bounds were not satisfied
--> src\lib.rs:131:24
|
131 | new_u8.set_bit(index, Bit(current_bit)).unwrap();
| ^^^^^^^ method cannot be called on `u8` due to unsatisfied trait bounds
note: trait bound `&mut u8: BitAnd` was not satisfied
--> src\lib.rs:168:8
|
166 | impl<T> BitMan for T
| ------ -
167 | where
168 | T: BitAnd<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`<&mut u8 as BitAnd>::Output = &mut u8`
`<&u8 as BitAnd>::Output = &u8`
--> src\lib.rs:168:15
|
166 | impl<T> BitMan for T
| ------ -
167 | where
168 | T: BitAnd<Output = Self>
| ^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `&mut u8: BitOr` was not satisfied
--> src\lib.rs:169:11
|
166 | impl<T> BitMan for T
| ------ -
...
169 | + BitOr<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`<&mut u8 as BitOr>::Output = &mut u8`
`<&u8 as BitOr>::Output = &u8`
--> src\lib.rs:169:17
|
166 | impl<T> BitMan for T
| ------ -
...
169 | + BitOr<Output = Self>
| ^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `&mut u8: Not` was not satisfied
--> src\lib.rs:170:11
|
166 | impl<T> BitMan for T
| ------ -
...
170 | + Not<Output = Self>
| ^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`<&mut u8 as Not>::Output = &mut u8`
`<&u8 as Not>::Output = &u8`
--> src\lib.rs:170:15
|
166 | impl<T> BitMan for T
| ------ -
...
170 | + Not<Output = Self>
| ^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `&mut u8: Shl` was not satisfied
--> src\lib.rs:171:11
|
166 | impl<T> BitMan for T
| ------ -
...
171 | + Shl<Output = Self>
| ^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`<&mut u8 as Shl>::Output = &mut u8`
`<&u8 as Shl>::Output = &u8`
--> src\lib.rs:171:15
|
166 | impl<T> BitMan for T
| ------ -
...
171 | + Shl<Output = Self>
| ^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`&mut u8: num::Zero`
`&u8: num::Zero`
--> src\lib.rs:173:11
|
166 | impl<T> BitMan for T
| ------ -
...
173 | + Zero
| ^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`&mut u8: One`
`&u8: One`
--> src\lib.rs:174:11
|
166 | impl<T> BitMan for T
| ------ -
...
174 | + One
| ^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`&mut u8: From<usize>`
`&u8: From<usize>`
`u8: From<usize>`
--> src\lib.rs:175:11
|
166 | impl<T> BitMan for T
| ------ -
...
175 | + From<usize>
| ^^^^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `&mut u8: Clone` was not satisfied
--> src\lib.rs:176:11
|
166 | impl<T> BitMan for T
| ------ -
...
176 | + Clone
| ^^^^^ unsatisfied trait bound introduced here
_
pub struct Bits(Vec<bool>);
impl<T> BitMan for T
where
T: BitAnd<Output = Self>
+ BitOr<Output = Self>
+ Not<Output = Self>
+ Shl<Output = Self>
+ Sized
+ Zero
+ One
+ From<usize>
+ Clone
+ PartialEq,
{
fn set_bit(mut self, index: usize, bit: Bit) -> Result<Bit, BitManError> {
if index > size_of::<Self>() {
return Err(BitManError::OutOfBounds(format!(
"Index {:?} is larger than total size {:?}.",
index,
size_of::<Self>()
)));
}
if bit.0 {
let mask: Self = Self::one();
let mask: Self = mask << (size_of::<Self>() - index).into();
self = self & !mask.clone();
return Ok(Bit(self & mask != Self::zero()));
} else {
let mask: Self = Self::one();
let mask: Self = mask << (size_of::<Self>() - index).into();
self = self | mask.clone();
return Ok(Bit(self & mask != Self::zero()));
}
}
}
impl From<Bits> for usize {
fn from(bits_to_convert: Bits) -> Self {
if bits_to_convert.0.len() > size_of::<usize>() {
let shortened_bits: Bits = Bits(
bits_to_convert.0
[(bits_to_convert.0.len() - size_of::<usize>())..bits_to_convert.0.len()]
.to_vec(),
);
usize::from(shortened_bits)
} else {
let mut new_usize: usize = Default::default();
for (index, current_bit) in bits_to_convert.0.clone().into_iter().enumerate() {
new_usize.set_bit(index, Bit(current_bit)).unwrap();
}
if bits_to_convert.0.len() < size_of::<usize>() {
new_usize = new_usize >> size_of::<usize>() - bits_to_convert.0.len();
}
new_usize
}
}
}
impl From<Bits> for u8 {
fn from(bits_to_convert: Bits) -> Self {
if bits_to_convert.0.len() > size_of::<u8>() {
let shortened_bits: Bits = Bits(
bits_to_convert.0
[(bits_to_convert.0.len() - size_of::<u8>())..bits_to_convert.0.len()]
.to_vec(),
);
u8::from(shortened_bits)
} else {
let mut new_u8: u8 = Default::default();
for (index, current_bit) in bits_to_convert.0.clone().into_iter().enumerate() {
new_u8.set_bit(index, Bit(current_bit)).unwrap();
}
if bits_to_convert.0.len() < size_of::<u8>() {
new_u8 = new_u8 >> size_of::<u8>() - bits_to_convert.0.len();
}
new_u8
}
}
}
The error is quite sizeable but I'll pick out one particular problematic portion and highlight it:
note: the following trait bounds were not satisfied:
`&mut u8: From<usize>`
`&u8: From<usize>`
`u8: From<usize>`
--> src\lib.rs:175:11
|
166 | impl<T> BitMan for T
| ------ -
...
175 | + From<usize>
| ^^^^^^^^^^^ unsatisfied trait bound introduced here
When the compiler sees new_u8.set_bit(...), it will try u8, &u8, and &mut u8 to try to match a trait implementation. But as you can see above, none of these types implement From<usize>. You can see this better if you call the trait method explicitly for the implementation you expect using the fully qualified syntax:
<u8 as BitMan>::set_bit(new_u8, ...)
error[E0277]: the trait bound `u8: From<usize>` is not satisfied
--> src/lib.rs:87:17
|
87 | <u8 as BitMan>::set_bit(new_u8, index, Bit(current_bit)).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<usize>` is not implemented for `u8`
|
= help: the following implementations were found:
<u8 as From<Bits>>
<u8 as From<NonZeroU8>>
<u8 as From<bool>>
<f32 as From<i16>>
and 73 others
Based on your wording, I'm guessing you're assuming it'd be implemented for u8, however usize can represent way more values than can fit in a u8, such conversion would be lossy. The TryFrom trait is used for conversions that can fail. Regardless, you should probably use T: Shl<usize, Output = Self> instead and drop the .into()s and From constraint. This compiles.
You should probably also change it to change self by mutable reference. Because you're passing self by value, right now it'd simply copy the usize/u8, modify it within the function, and then do nothing with it; it won't modify the original value.
If I want to create a Cartesian product of a list of lists in Haskell, I can do this:
product [] = [[]]
product (xs:xss) = concatMap (\k -> map (k:) (product1 xss)) xs
or even this:
sequence xss
I'm trying to implement an efficient iterator that would do the same in Rust, but I'm not sure what is wrong with my attempt:
use std::iter::{empty, once};
fn product<T, I, V>(xss: I) -> Box<Iterator<Item = Iterator<Item = T>>>
where
T: Clone,
V: IntoIterator<Item = T>,
I: IntoIterator<Item = V>,
{
Box::new(xss.into_iter().fold(once(empty()), |acc, xs| {
xs.into_iter().flat_map(|x| acc.map(|ys| ys.chain(once(x))))
}))
}
fn main() {
let data = vec![[1, 2, 3], [10, 20, 30], [100, 200, 300]];
let it: Vec<Vec<u32>> = product(data).collect();
println!("{:?}", it);
}
(playground)
Produces these errors:
error[E0308]: mismatched types
--> src/main.rs:10:9
|
10 | xs.into_iter().flat_map(|x| acc.map(|ys| ys.chain(once(x))))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::iter::Once`, found struct `std::iter::FlatMap`
|
= note: expected type `std::iter::Once<std::iter::Empty<T>>`
found type `std::iter::FlatMap<<V as std::iter::IntoIterator>::IntoIter, std::iter::Map<std::iter::Once<std::iter::Empty<T>>, [closure#src/main.rs:10:45: 10:67 x:_]>, [closure#src/main.rs:10:33: 10:68 acc:_]>`
error[E0271]: type mismatch resolving `<std::iter::Once<std::iter::Empty<T>> as std::iter::Iterator>::Item == std::iter::Iterator<Item=T>`
--> src/main.rs:9:5
|
9 | / Box::new(xss.into_iter().fold(once(empty()), |acc, xs| {
10 | | xs.into_iter().flat_map(|x| acc.map(|ys| ys.chain(once(x))))
11 | | }))
| |_______^ expected struct `std::iter::Empty`, found trait std::iter::Iterator
|
= note: expected type `std::iter::Empty<T>`
found type `std::iter::Iterator<Item=T>`
= note: required for the cast to the object type `std::iter::Iterator<Item=std::iter::Iterator<Item=T>>`
error[E0277]: the trait bound `[{integer}; 3]: std::iter::Iterator` is not satisfied
--> src/main.rs:16:29
|
16 | let it: Vec<Vec<u32>> = product(data).collect();
| ^^^^^^^ `[{integer}; 3]` is not an iterator; maybe try calling `.iter()` or a similar method
|
= help: the trait `std::iter::Iterator` is not implemented for `[{integer}; 3]`
= note: required because of the requirements on the impl of `std::iter::IntoIterator` for `[{integer}; 3]`
= note: required by `product`
error: the `collect` method cannot be invoked on a trait object
--> src/main.rs:16:43
|
16 | let it: Vec<Vec<u32>> = product(data).collect();
| ^^^^^^^
The first error is giving me the feeling that Rust cannot even create a lazily consumed iterator with fold because Empty<T> is an Iterator<Item = T> (at least conceptually), but I hope I'm wrong.
For what its worth, the Itertools crate implements a workable cartesian product function:
use itertools::Itertools;
let it = (0..2).cartesian_product("αβ".chars());
itertools::assert_equal(it, vec![(0, 'α'), (0, 'β'), (1, 'α'), (1, 'β')]);
The first reason your approach is bound to fail is because you're trying to transpose an algorithm designed to work on lists into an algorithm working on iterators. Lists are suitable for a functional approach, iterators aren't, because they have a state. The next(&mut self) function won't return the same value each time it's called with the same argument, whereas a next(x:xs) function will. This is the reason why the implementation found in itertools clones iterators: to save their initial state and recover it for the next iteration over the set.
The second reason, the one behind the error messages, is that you're fighting against Rust's type system. The result values of all your calls to iterator functions (fold, flat_map, etc.) aren't trait objects but 'concrete types'. For instance iterator.fold(init, fn)'s result type is init's type. That's why the compiler complains when you pass fold a lambda that doesn't return a std::iter::Empty<T>.
But it gets worse. You could imagine to coerce or cast that std::iter::Empty<T> into a trait object. Alas, object safety is required. To put it in a nutshell, "A good intuition is “except in special circumstances, if your trait’s method uses Self, it is not object-safe.". But iterators' main method is next(&mut self).
I am trying to slice a vector and print it simultaneously in Rust. This is my code:
fn main() {
let a = vec![1, 2, 3, 4];
println!("{:?}", a[1..2]);
}
Error:
error[E0277]: the trait bound `[{integer}]: std::marker::Sized` is not satisfied
--> src/main.rs:6:5
|
6 | println!("{:?}", a[1..3]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `[{integer}]: std::marker::Sized` not satisfied
|
= note: `[{integer}]` does not have a constant size known at compile-time
= note: required by `std::fmt::ArgumentV1::new`
= note: this error originates in a macro outside of the current crate
How do I print this sliced vector?
You need to use a reference; it worked for me in Rust 1.13.
println!("{:?}", &a[1..3]);
Here's an example of what I'm trying to do:
for &xs in &[&[1, 2, 3].iter().map(|x| x + 1)] {
for &x in xs {
println!("{}", x);
}
}
This gives me the following error:
error[E0277]: the trait bound `&std::iter::Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:2:40: 2:49]>: std::iter::Iterator` is not satisfied
--> src/main.rs:3:9
|
3 | / for &x in xs {
4 | | println!("{}", x);
5 | | }
| |_________^ the trait `std::iter::Iterator` is not implemented for `&std::iter::Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:2:40: 2:49]>`
|
= note: `&std::iter::Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:2:40: 2:49]>` is not an iterator; maybe try calling `.iter()` or a similar method
= note: required by `std::iter::IntoIterator::into_iter`
...which is very surprising, because I clearly see how std::Iter::Map implements Iterator.
Why does it complain and how to iterate over a slice of mapped slices?
&T can't be iterated as next mutates.
Thus if you have a &Map<_, _>, you can't iterate it.
You might not realize that &[1,2,3].iter().map(|&x| x+1) means
&([1,2,3].iter().map(|&x| x+1))
giving the reference.
Using for &xs in &[&mut ...] won't work either, as it requires moving xs out of an immutable reference. There is also currently no by-value iterator over fixed length arrays. I believe the easiest solution is
for xs in &mut [&mut [1, 2, 3].iter().map(|&x| x+1)] {
for x in xs {
println!("{}", x);
}
}
Note that this also requires fixing a problem with the map call, which didn't dereference its input.