How can a range be used in a Vec? - rust

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

Related

TrustedLen Iterator from an Iterator that is not implementing TrustedLen

I'm new to Rust, so this may be a naive question, but I was looking at the TrustedLen trait and was confused. It describes that a TrustedLen iterator
"reports a size hint where it is either exact (lower bound is equal to upper bound), or the upper bound is None." I was curious about the cases where we create a TrustedLen iterator, from another iterator that doesn't implement the TrustedLen.
pub fn main() -> () {
let v = vec![1, 2, 3, 4, 5];
let (lower, upper) = v.iter().filter(|num| {*num % 2 == 0}).take(2).size_hint();
println!("({},{})", lower, upper.unwrap());
}
This produces the message
(0,2)
Here the lower bound doesn't match the upper bound, because of the filter predicate, however I'm calling size_hint on a Take iterator which implements TrustedLen.
Take implements TrustedLen conditionally only when the inner iterator is TrustedLen. In this case, Filter is not, so the iterator is not TrustedLen:
#![feature(trusted_len)]
fn require_trusted_len(_: impl std::iter::TrustedLen) {}
fn main() {
let v = vec![1, 2, 3, 4, 5];
let iter = v.iter().filter(|num| {*num % 2 == 0}).take(2);
require_trusted_len(iter);
}
Yields:
error[E0277]: the trait bound `Filter<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:8:32: 8:37]>: TrustedLen` is not satisfied
--> src/main.rs:9:25
|
9 | require_trusted_len(iter);
| ------------------- ^^^^ the trait `TrustedLen` is not implemented for `Filter<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:8:32: 8:37]>`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `TrustedLen`:
&mut I
ArrayChunksMut<'_, T, N>
Chunks<'_, T>
ChunksExact<'_, T>
ChunksExactMut<'_, T>
ChunksMut<'_, T>
Cloned<I>
Copied<I>
and 44 others
= note: required for `std::iter::Take<Filter<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:8:32: 8:37]>>` to implement `TrustedLen`
note: required by a bound in `require_trusted_len`
--> src/main.rs:3:32
|
3 | fn require_trusted_len(_: impl std::iter::TrustedLen) {}
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `require_trusted_len`

Rust Polars Series compare to scalar not working

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

How can I build a `Vec<i32>` from an `Iterator<Item=&i32>`?

I encountered an error when trying to use a function get_even_numbers() to borrow a vec v by passing it in by reference &v instead of by value v.
fn get_even_numbers(v: &Vec<i32>) -> Vec<i32> {
v.iter().filter(|x| x % 2 == 0).collect()
}
fn main() {
let v: Vec<i32> = (0..10).collect();
let even: Vec<i32> = get_even_numbers(&v);
println!("Even numbers: {:?}", even);
}
error[E0277]: a value of type `Vec<i32>` cannot be built from an iterator over elements of type `&i32`
--> src/main.rs:2:37
|
2 | v.iter().filter(|x| x % 2 == 0).collect()
| ^^^^^^^ value of type `Vec<i32>` cannot be built from `std::iter::Iterator<Item=&i32>`
|
= help: the trait `FromIterator<&i32>` is not implemented for `Vec<i32>`
= help: the trait `FromIterator<T>` is implemented for `Vec<T>`
note: required by a bound in `collect`
Why does the above give an error, but passing it in by value does not, as shown below?
fn get_even_numbers(v: Vec<i32>) -> Vec<i32> {
v.into_iter().filter(|x| x % 2 == 0).collect()
}
fn main() {
let v: Vec<i32> = (0..10).collect();
let even: Vec<i32> = get_even_numbers(v);
println!("Even numbers: {:?}", even);
}
Even numbers: [0, 2, 4, 6, 8]
I used .iter() inside the function when passing in by reference and .into_iter() when passing in by value, not sure if these are the correct functions to use.
Use v.iter().filter(|x| x % 2 == 0).cloned().collect(). That will (trivially) clone each of the &i32 references into actual i32 values.

How to split a string in Rust with multiple parameters?

I am trying to split a string in Rust using both whitespace and ,. I tried doing
let v: Vec<&str> = "Mary had a little lamb".split_whitespace().collect();
let c: Vec<&str> = v.split(',').collect();
The result:
error[E0277]: the trait bound `for<'r> char: std::ops::FnMut<(&'r &str,)>` is not satisfied
--> src/main.rs:3:26
|
3 | let c: Vec<&str> = v.split(',').collect();
| ^^^^^ the trait `for<'r> std::ops::FnMut<(&'r &str,)>` is not implemented for `char`
error[E0599]: no method named `collect` found for type `std::slice::Split<'_, &str, char>` in the current scope
--> src/main.rs:3:37
|
3 | let c: Vec<&str> = v.split(',').collect();
| ^^^^^^^
|
= note: the method `collect` exists but the following trait bounds were not satisfied:
`std::slice::Split<'_, &str, char> : std::iter::Iterator`
`&mut std::slice::Split<'_, &str, char> : std::iter::Iterator`
Use a closure:
let v: Vec<&str> = "Mary had a little lamb."
.split(|c| c == ',' || c == ' ')
.collect();
This is based upon the String documentation.
Pass a slice with the chars to it:
fn main() {
let s = "1,2 3";
let v: Vec<_> = s.split([' ', ','].as_ref()).collect();
assert_eq!(v, ["1", "2", "3"]);
}
split takes an argument of type Pattern. To see what concretely you can pass as parameter, see the implementors

Slice and iter() simultaneously

I am trying to figure out why this does not work (Playground):
fn main() {
let a = vec![1, 2, 3, 4];
let b = a.clone();
// slice and iter (wrong way)
let s: i32 = &a[1..a.len()].iter()
.zip(&b[1..b.len()].iter())
.map(|(x, y)| x * y)
.sum();
println!("{}", s);
}
Error:
rustc 1.13.0 (2c6933acc 2016-11-07)
error[E0277]: the trait bound `&std::slice::Iter<'_, {integer}>: std::iter::Iterator` is not satisfied
--> <anon>:6:10
|
6 | .zip(&b[1..b.len()].iter())
| ^^^ trait `&std::slice::Iter<'_, {integer}>: std::iter::Iterator` not satisfied
|
= note: `&std::slice::Iter<'_, {integer}>` is not an iterator; maybe try calling `.iter()` or a similar method
= note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&std::slice::Iter<'_, {integer}>`
error: no method named `map` found for type `std::iter::Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` in the current scope
--> <anon>:7:10
|
7 | .map(|(x, y)| x * y)
| ^^^
|
= note: the method `map` exists but the following trait bounds were not satisfied: `&std::slice::Iter<'_, {integer}> : std::iter::Iterator`, `std::iter::Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>> : std::iter::Iterator`
But this does work:
fn main() {
let a = vec![1, 2, 3, 4];
let b = a.clone();
// slice and iter (correct way)
let s: i32 = a[1..a.len()].iter()
.zip(b[1..b.len()].iter())
.map(|(x, y)| x * y)
.sum();
println!("{}", s);
}
Please explain how vectors work in Rust and the difference above when I iter().
In short: you probably misunderstood operator precedence:
&b[1..b.len()].iter()
Is equal to:
&(b[1..b.len()].iter())
And since zip() is expecting something that implements IntoIterator, the call fails, since a reference to this iterator type does not implement said trait.
Full Explanation
Let's try to understand the error message! Of course, we will first just look at the first error:
error[E0277]: the trait bound `&std::slice::Iter<'_, {integer}>: std::iter::Iterator` is not satisfied
--> <anon>:6:10
|
6 | .zip(&b[1..b.len()].iter())
| ^^^ trait `&std::slice::Iter<'_, {integer}>: std::iter::Iterator` not satisfied
|
= note: `&std::slice::Iter<'_, {integer}>` is not an iterator; maybe try calling `.iter()` or a similar method
= note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&std::slice::Iter<'_, {integer}>`
Wow, that's quite a mouthful. But we can see that some trait bound requirement of the function zip() is violated. So, let's look at the signature of said function:
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
where U: IntoIterator
What matters is the other argument (type U). U has to be IntoIterator. This trait is implemented for quite a few types ... let's check what type we're trying to pass into zip():
&b[1..b.len()].iter()
To analyze this completely, we need to understand quite something, but I'll try to break it down. First, let's disambiguate operator precedence by inserting more parenthesis. The above code snippet is equivalent to:
&(b[1..b.len()].iter())
An expression foo[bar] desugares to *::std::ops::Index::index(&foo, bar). This is the most complex part here, but looking this up in the documentation reveals that the expression b[1..b.len()] has the type [i32].
On that type, you call iter() which returns a type Iter<_, _> which is the iterator type for slices.
Now the&: you borrow this Iter<_, _> thing, resulting in &Iter<_, _>.
And hey, this matches the error message! Look at the last note:
note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&std::slice::Iter<'_, {integer}>`
So... what does satisfy the IntoIterator trait? For one, every type that implements Iterator (e.g. Iter<_, _>) also implements IntoIterator. So you can just remove the & in the expression and it works!
But we can do even better! IntoIterator is also implemented for &[T], so you can also just remove the .iter() and it works!
Working Code
let s: i32 = a[1..].iter()
.zip(&b[1..])
.map(|(x, y)| x * y)
.sum();
Note: I also removed the ranges' upper bounds to make them half open, as Paolo Falabella suggested.
Your first version has an issue with operator precedence: &a[1..a.len()].iter() applies iter() first and then takes a reference to it, ending with a reference to a std::slice::Iter.
As you can see on the docs for Iter , there is an impl Iterator for Iter but not for &Iter.
This is what the first error is trying to say: (look at the part that says: &std::slice::Iter<'_, {integer}> is not an iterator).
Simplifying a bit, you can have:
fn main() {
let a = vec![1, 2, 3, 4];
// let b = a.clone(); // no more need to clone. We're going to only
// work with references
let s: i32 = (&a[1..]).iter() // you don't need the a.len()
// to slice to the end
.zip(&a[1..]) // &a implements IntoIter, which zip
// accepts, so you don't need iter()
.map(|(x, y)| x * y)
.sum();
println!("{}", s);
}
Iterator::zip expects something that implements IntoIterator.
Instead of passing an Iterator, you're passing a reference to the Iterator. Iterators mutate, and a reference isn't sufficient.
You can resolve this by using parenthesis to make it clear what you're trying to grab a reference from
fn main() {
let a = vec![1, 2, 3, 4];
let b = a.clone();
let s: i32 = (&a)[1..a.len()].iter()
.zip(((&b)[1..b.len()]).iter())
.map(|(x, y)| x * y)
.sum();
println!("{}", s);
}

Resources