Rust Polars Series compare to scalar not working - rust

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));
}

Related

Checking if even on a generic type in Rust [duplicate]

This question already has an answer here:
In Rust, how can I restrict a generic T to allow modulus?
(1 answer)
Closed last year.
I have the following code
pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T> {
iter.filter(|x| x % 2 == 0)
}
But it doesn't compile because
error[E0369]: cannot mod `&T` by `{integer}`
--> src/lib.rs:10:23
|
10 | iter.filter(|x| x % 2 == 0)
| - ^ - {integer}
| |
| &T
|
help: consider restricting type parameter `T`
|
9 | pub fn evens<T: std::ops::Rem<Output = {integer}>>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T> {
| +++++++++++++++++++++++++++++++++++
What do I need to do to operate on T type to check if it is even? I tried casting T but that didn't work.
I also tried using the suggested function signature in the error message, but that led to a whole host of new problems:
error: cannot constrain an associated constant to a value
--> src/lib.rs:9:31
|
9 | pub fn evens<T: std::ops::Rem<Output = {integer}>>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T> {
| ------^^^---------
| | |
| | ...cannot be constrained to this value
| this associated constant...
error[E0282]: type annotations needed
--> src/lib.rs:10:10
|
10 | iter.filter(|x| x % 2 == 0)
| ^^^^^^ cannot infer type
|
= note: type must be known at this point
error[E0599]: no method named `filter` found for type parameter `impl Iterator<Item = T>` in the current scope
--> src/lib.rs:10:10
|
10 | iter.filter(|x| x % 2 == 0)
| ^^^^^^ method not found in `impl Iterator<Item = T>`
|
= note: `iter` is a function, perhaps you wish to call it
= help: items from traits can only be used if the type parameter is bounded by the trait
Assuming you want to filter on INDEX (and not VALUE), then the following code works:
pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T> {
iter.enumerate().filter(|(i, _)| i % 2 == 0).map(|(_, e)| e)
}

Unexpected "method not found" compiler error

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));
}

How to return a Filter iterator filtering by struct members

I am trying to write a Tic-Tac-Toe game on the console. For one method of my Board struct, I'd like to return all positions of a certain type.
type PlayerID = i32;
type Position = (usize, usize);
#[derive(PartialEq)]
pub enum TileState {
Player(PlayerID),
None,
}
pub struct Board {
board: [[TileState; 3]; 3],
}
impl Board {
const ALL_POSITIONS: [Position; 3] = [(0, 0), (0, 1), (0, 2)];
pub fn free_tiles<'a>(&'a self) -> impl Iterator<Item = Position> + 'a {
Board::ALL_POSITIONS
.iter()
.filter(|(x, y)| self.board[*x][*y] == TileState::None)
.cloned()
}
}
Compiler error:
error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
--> src/lib.rs:20:21
|
20 | .filter(|(x, y)| self.board[*x][*y] == TileState::None)
| ^^^^^^^^ ---- `self` is borrowed here
| |
| may outlive borrowed value `self`
|
note: closure is returned here
--> src/lib.rs:18:9
|
18 | / Board::ALL_POSITIONS
19 | | .iter()
20 | | .filter(|(x, y)| self.board[*x][*y] == TileState::None)
21 | | .cloned()
| |_____________________^
help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
|
20 | .filter(move |(x, y)| self.board[*x][*y] == TileState::None)
| ^^^^^^^^^^^^^
Preferably, I'd like to avoid having to copy ALL_POSITIONS, self.board or create a new array in any other way.
What would be the best Rust style to solve this problem?

Reference traits: no implementation for `&T * &T`

I try to write generic method and specify some type T: num_traits::float::Float from num-traits crate. How should I ask &T to implement basic numeric methods such as multiplication?
use splines::{Interpolation, Key, Spline, interpolate};
use num_traits::{float::Float, identities};
use conv::prelude::*;
struct Interpolator<T>
where T: Float + interpolate::One + interpolate::Trigo {
target_x: Vec<T>,
}
impl<T> Interpolator<T>
where T: Float + interpolate::One + interpolate::Trigo {
fn interpolate<U>(&self, x: &[T], y: &[U]) -> Vec<U>
where U: Float + identities::Zero {
assert_eq!(x.len(), y.len());
let key_iter = x.iter().zip(y).map(|(x, y)| Key::new(x, y, Interpolation::Linear));
let spline = Spline::from_iter(key_iter);
let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
result
}
}
fn main() {
}
Cargo.toml
[package]
name = "name"
version = "0.1.0"
edition = "2018"
[dependencies]
conv = "0.3.2"
splines = "1.0.0-rc.3"
num-traits = "0.2"
Compilation errors:
error[E0277]: the trait bound `&T: splines::interpolate::One` is not satisfied
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ the trait `splines::interpolate::One` is not implemented for `&T`
error[E0277]: the trait bound `&T: splines::interpolate::Trigo` is not satisfied
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ the trait `splines::interpolate::Trigo` is not implemented for `&T`
error[E0277]: cannot multiply `&T` to `&T`
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ no implementation for `&T * &T`
|
= help: the trait `std::ops::Mul` is not implemented for `&T`
= help: consider adding a `where &T: std::ops::Mul` bound
error[E0277]: cannot divide `&T` by `&T`
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ no implementation for `&T / &T`
|
= help: the trait `std::ops::Div` is not implemented for `&T`
= help: consider adding a `where &T: std::ops::Div` bound
error[E0277]: the trait bound `&U: splines::interpolate::Interpolate<&T>` is not satisfied
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ the trait `splines::interpolate::Interpolate<&T>` is not implemented for `&U`
error[E0277]: cannot add `&T` to `&T`
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ no implementation for `&T + &T`
|
= help: the trait `std::ops::Add` is not implemented for `&T`
= help: consider adding a `where &T: std::ops::Add` bound
= note: required because of the requirements on the impl of `splines::interpolate::Additive` for `&T`
error[E0277]: cannot subtract `&T` from `&T`
--> src/main.rs:18:66
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^ no implementation for `&T - &T`
|
= help: the trait `std::ops::Sub` is not implemented for `&T`
= help: consider adding a `where &T: std::ops::Sub` bound
= note: required because of the requirements on the impl of `splines::interpolate::Additive` for `&T`
error[E0277]: the trait bound `&U: num_traits::identities::Zero` is not satisfied
--> src/main.rs:18:86
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^^^^^^^^^^^ the trait `num_traits::identities::Zero` is not implemented for `&U`
|
= note: required by `num_traits::identities::zero`
error[E0277]: a collection of type `std::vec::Vec<U>` cannot be built from an iterator over elements of type `&U`
--> src/main.rs:18:107
|
18 | let result: Vec<U> = self.target_x.iter().map(|x| spline.sample(x).unwrap_or(identities::zero())).collect();
| ^^^^^^^ a collection of type `std::vec::Vec<U>` cannot be built from `std::iter::Iterator<Item=&U>`
|
= help: the trait `std::iter::FromIterator<&U>` is not implemented for `std::vec::Vec<U>`
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0277`.
error: Could not compile `trait_generic`.
Maybe you could just consider using Key::new(*x, *y, Interpolation::Linear) and spline.sample(*x)?

How can a range be used in a Vec?

This code works fine:
fn main() {
let v: i32 = vec![1, 2, 3, 4, 5].iter().map(|&x: &i32| x.pow(2)).sum();
println!("{}", v);
}
I tried to replace the vec![1, 2, 3, 4, 5] with vec![1..5] but iter and map did not work:
error[E0631]: type mismatch in closure arguments
--> src/main.rs:2:36
|
2 | let v: i32 = vec![1..5].iter().map(|&x: &i32| x.pow(2)).sum();
| ^^^ ------------------- found signature of `for<'r> fn(&'r i32) -> _`
| |
| expected signature of `fn(&std::ops::Range<{integer}>) -> _`
error[E0599]: no method named `sum` found for type `std::iter::Map<std::slice::Iter<'_, std::ops::Range<{integer}>>, [closure#src/main.rs:2:40: 2:59]>` in the current scope
--> src/main.rs:2:61
|
2 | let v: i32 = vec![1..5].iter().map(|&x: &i32| x.pow(2)).sum();
| ^^^
|
= note: the method `sum` exists but the following trait bounds were not satisfied:
`std::iter::Map<std::slice::Iter<'_, std::ops::Range<{integer}>>, [closure#src/main.rs:2:40: 2:59]> : std::iter::Iterator`
`&mut std::iter::Map<std::slice::Iter<'_, std::ops::Range<{integer}>>, [closure#src/main.rs:2:40: 2:59]> : std::iter::Iterator`
I've also asked this question on the Rust user's forum.
A range like 1..5 is already an iterator, so you do not have to call iter() to create one:
let v: i32 = (1..5).map(|x: i32| x.pow(2)).sum();
Also note that the references are gone because this iterator iterates over values.
If you absolutly need a Vec, you need to collect the range into it first:
let v: i32 = (1..5)
.collect::<Vec<i32>>()
.iter()
.map(|&x: &i32| x.pow(2))
.sum();

Resources