I am using ndarray and trying to slice some arrays. This works
let y = arr2(&[[ 6, 5, 4],
[12, 11, 10]]);
let ip = y.slice(s![0, ..]);
println!("IP {}", ip);
but this
let y = arr2(&[[ 6, 5, 4],
[12, 11, 10]]);
let ip = y.slice(s![0, ..]);
println!("IP {}", ip[0]);
does not compile. What is going on?
Compile errors are:
Error[E0277]: the trait bound `i32: Dimension` is not satisfied
....
println!("IP {}", ip[0]);
| ^^^^^ the trait `Dimension` is not implemented for `i32`
| = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `ArrayBase<ViewRepr<&i32>, i32>`
with other errors
error[E0308]: mismatched types
....
| let ip = y.slice(s![0, ..]);
| ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Dim`
|
= note: expected type `i32`
found struct `Dim<[usize; 1]>`
The issue is that integer literals are by default i32, and so ip[0] tells Rust that ip: Index<i32>, which then fixes the type of slice's argument to be i32, but the type is supposed to be impl Dimension. (I don't fully understand the type hierarchy of ndarray's indices/dimensions, but this is close enough to be useful.) To work around this, simple replace ip[0] with ip[0_usize].
Related
I was trying to use Chain in Rust and encountered a problem that seems strange to me. I tried two code snippets that one of them works and the other doesn't. I tried to figure out the problem from the error message emitted by the compiler but couldn't find anything useful.
Snippet 1
fn main() {
let v: Vec<_> = (1..5).collect();
let u = v.iter().chain([6, 7, 8, 9, 10].iter().map(|i| i ));
u.for_each(|i| println!("{i}"));
}
Snippet 2
fn main() {
let v: Vec<_> = (1..5).collect();
let u = v.iter().chain([6, 7, 8, 9, 10].iter().map(|i| i+1 ));
u.for_each(|i| println!("{i}"));
}
The first snippet runs successfully but the second fails. The error message is:
Compiling playground v0.0.1 (/playground)
error[E0271]: type mismatch resolving `<[closure#src/main.rs:5:56: 5:63] as FnOnce<(&{integer},)>>::Output == &{integer}`
--> src/main.rs:5:28
|
5 | let u = v.iter().chain([6, 7, 8, 9, 10].iter().map(|i| i+1 ));
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&{integer}`, found integer
| |
| required by a bound introduced by this call
|
= note: required because of the requirements on the impl of `Iterator` for `Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:5:56: 5:63]>`
note: required by a bound in `std::iter::Iterator::chain`
error[E0599]: the method `for_each` exists for struct `std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:5:56: 5:63]>>`, but its trait bounds were not satisfied
--> src/main.rs:6:7
|
6 | u.for_each(|i| println!("{i}"));
| ^^^^^^^^ method cannot be called on `std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:5:56: 5:63]>>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`<Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:5:56: 5:63]> as Iterator>::Item = &{integer}`
which is required by `std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:5:56: 5:63]>>: Iterator`
`std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:5:56: 5:63]>>: Iterator`
which is required by `&mut std::iter::Chain<std::slice::Iter<'_, {integer}>, Map<std::slice::Iter<'_, {integer}>, [closure#src/main.rs:5:56: 5:63]>>: Iterator`
Some errors have detailed explanations: E0271, E0599.
For more information about an error, try `rustc --explain E0271`.
error: could not compile `playground` due to 2 previous errors
I'm new to Rust and not familiar with many details. Can someone explain to me what's the problem here? Why changing the i to i+1 can cause a compile-time error?
This succeeds in the first case because both iterators are producing &i32 items. However, in the second case the first iterator is producing &i32 items, while the second iterator is producing i32 items -- the addition operation auto-derefs i and produces an integer. To chain two iterators, the item types must match exactly.
To clarify, the closures given to map in both snippets differ in their signature, which may be surprising since they look nearly identical!
|i| i accepts an &i32 and returns that &i32. In snippet 1, this is equivalent to |i: &i32| -> &i32 { i }.
|i| i + 1 accepts an &i32 and returns an i32, which is not the same type. In snippet 2, this is equivalent to |i: &i32| -> i32 { *i + 1 }.
To fix this, use the copied utility to convert the first iterator from &i32 items to i32 items by copy, which will match the type of the second iterator, allowing chaining:
fn main() {
let v: Vec<_> = (1..5).collect();
let u = v.iter().copied().chain([6, 7, 8, 9, 10].iter().map(|i| i+1 ));
u.for_each(|i| println!("{i}"));
}
Alternatively, convert the Vec to an interator with into_iter, which will consume the Vec and produce its values directly (not as references).
fn main() {
let v: Vec<_> = (1..5).collect();
let u = v.into_iter().chain([6, 7, 8, 9, 10].iter().map(|i| i+1 ));
u.for_each(|i| println!("{i}"));
}
Type inference can be handy, but it can also hide information from you. When you run into "type mismatch" errors like this and you can't figure them out, a good way to diagnose the problem is to start adding type annotations based on what you think the types actually are. Either an added type annotation will fix the problem by forcing a type that was incorrectly inferred, or Rust will complain that the type annotation doesn't match an actual type, which will expose your incorrect assumption and from there you should be able to solve the problem.
In this particular case, adding the return type annotation -> &i32 to the second closure would have led to a much more understandable error:
error[E0308]: mismatched types
--> src/main.rs:6:28
|
6 | .map(|i| -> &i32 { i+1 } )
| ^^^
| |
| expected `&i32`, found integer
| help: consider borrowing here: `&(i+1)`
The compiler's suggestion is incorrect, but this makes the situation much clearer and helps you see that your closure was returning i32 when you thought from your first snippet that it would return &i32.
I am trying to solve an online challenge that involves comparing two sets. I followed this answer to convert my Vec<i32> output to HashSet
use std::collections::HashSet;
use std::iter::FromIterator;
struct Solution {}
impl Solution {
pub fn solve(nums: Vec<i32>, k: i32) -> Vec<i32> {
// todo, return dummy for now
return vec![1, 2];
}
}
fn main() {
assert_eq!(
HashSet::from_iter(Solution::solve(vec![1, 2, 3], 2)),
HashSet::from_iter(vec![1i32, 2i32])
)
}
For reasons I don't understand yet, the compilation fails:
error[E0282]: type annotations needed
--> src/main.rs:15:9
|
15 | HashSet::from_iter(Solution::solve(vec![1, 2, 3], 2)),
| ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `S` declared on the struct `HashSet`
It works fine for HashSet::from_iter(vec![1i32, 2i32])
I tried adding a type annotation like HashSet::from_iter::<Vec<i32>> with no avail. I also read the source implementation but still can't figure out what makes the compiler complain.
I can work around it by declaring it explicitly or construct the HashSet with a for loop and inserts, but I would like to understand what is going on here.
I'm using Rust 1.43.1.
I believe the answer from Kitsu is subtly incorrect since it suggests that Rust cannot infer the type of T because here may be an iterator implemented for a type P that collects a different type T (more on this at the end).
What's really happening
In fact, type inference for type S in HashSet<T, S> has nothing to do with the type of T. The issue is that there is no information in your program that allows the compiler to infer the type of S.
It is correct that adding a type parameter is sufficient to resolve the ambiguity:
HashSet::<i32>::from_iter(vec![1, 2, 3]);
This has nothing to do with the actual type you specify. Indeed, this works as well:
HashSet::<_>::from_iter(vec![1, 2, 3]);
The reason is that the definition of HashSet in the standard library includes a default type for S:
pub struct HashSet<T, S = RandomState> {
base: base::HashSet<T, S>,
}
By writing HashSet::<_>::from_iter(vec![1, 2, 3]); you're telling the compiler that it should use the default type for S, which is RandomState.
What about multiple implementations?
Kitsu's answer states that type inference fails for S because there might be multiple implementations of FromIterator. This is incorrect, but having multiple implementations can cause type inference to fail for T.
Consider this example:
fn iterator_demo() {
use std::collections::HashSet;
use std::hash::{BuildHasher, Hash};
use std::iter::FromIterator;
struct Empty;
impl<T, S> FromIterator<Empty> for HashSet<T, S>
where
T: Eq + Hash,
S: BuildHasher + Default,
{
fn from_iter<I>(iter: I) -> HashSet<T, S>
where
I: IntoIterator<Item = Empty>,
{
iter.into_iter().for_each(drop);
HashSet::default()
}
}
let x = HashSet::<_>::from_iter(vec![Empty, Empty]);
}
This causes type inference to fail; note that this is a failure to infer T, not S:
error[E0282]: type annotations needed for `HashSet<T>`
--> src/lib.rs:22:13
|
22 | let x = HashSet::<_>::from_iter(vec![Empty, Empty]);
| - ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
| |
| consider giving `x` the explicit type `HashSet<T>`, with the type parameters specified
Specifying the type resolves this ambiguity:
let x = HashSet::<String>::from_iter(vec![Empty, Empty]);
Credit to matt1992 on the Rust Discord for helping me to understand what's really happening here.
Let's look at the FromIterator::from_iter declaration, you've been using:
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = A>,
After specifying HashSet compiler can deduce that Self is HashSet<S> for some S. T for your particular case can be deduced as a Vec<i32>: IntoIterator<Item = i32> (for the second line that is resolved after you explicitly specified an integer type).
But still, S is not deduced because, in general, you may have an implementation that collects HashSet<u64> from IntoIterator<Item = u8>. So compiler cannot understand what are items of the collected type. Then if you swap the expressions of the assert_eq error source changes:
assert_eq!(
HashSet::from_iter(vec![1i32, 2i32]),
/*
|
15 | HashSet::from_iter(vec![1i32, 2i32]),
| ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `S` declared on the struct `HashSet`
*/
HashSet::from_iter(Solution::solve(vec![1, 2, 3], 2)),
)
The solution is fairly straightforward: you need to specify the item type of your HashSet:
assert_eq!(
HashSet::<i32>::from_iter(Solution::solve(vec![1, 2, 3], 2)),
HashSet::from_iter(vec![1i32, 2])
)
Raw idea
In a dummy project I have, I would like to use cycling iterators (to generate integers for example).
use std::iter::Cycle;
type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let mut cycles = [
[1, 2].iter().cycle(),
[2, 4].iter().cycle(),
];
cycles
}
fn main() {
let mut cycles = generate_cycles();
// ...
}
Refactor
Although the previous piece of code works as intended, my real world example is a bit more complicated, so I am looking to adapt the generate_cycles function to be able to perform more operations (in the following example, multiply by 2, then generate the cycling iterators).
For this, I tried to use arraymap:
extern crate arraymap;
use arraymap::ArrayMap;
use std::iter::Cycle;
type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let mut cycles = [
[1, 2],
[2, 4],
];
cycles
.map(|points| {
points.map(|point| point*2)
})
.map(|points| {
points.iter().cycle()
})
}
fn main() {
let mut cycles = generate_cycles();
// ...
}
The problem
The above solution does not work, and, as a Rust beginner recently exposed to the concept of "lifetime", I do not understand why the compiler is complaining here, or what I can do to make him happy.
error[E0495]: cannot infer an appropriate lifetime for autorefdue to conflicting requirements
--> src/main.rs:20:14
|
20 | points.iter().cycle()
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 19:10...
--> src/main.rs:19:10
|
19 | .map(|points| {
| __________^
20 | | points.iter().cycle()
21 | | })
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:20:7
|
20 | points.iter().cycle()
| ^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected [std::iter::Cycle<std::slice::Iter<'static, i32>>; 2]
found [std::iter::Cycle<std::slice::Iter<'_, i32>>; 2]
Here is a REPL with the code trying to make use of the arraymap: https://repl.it/repls/ShadowyStrikingFirm .
In your type declaration:
type IntegerCycle = Cycle<std::slice::Iter<'static, i32>>;
You say that you the underlying slices you use to build your iterators must have 'static lifetime, that is, they must live forever. Then you use literal arrays such as [1, 2] that, as all literals, have 'static' lifetime and all goes well:
let r: &'static [i32; 2] = &[1, 2]; //Ok
But then, you try a code similar to this simpler one:
let a = [1, 2].map(|x| 2 * x);
let r: &'static [i32; 2] = &a; //error: borrowed value does not live long enough
That is the result of arraymap::map is a normal array, not a literal one, so it does not have a 'static lifetime. It cannot be static because you are computing the values in runtime. It will live as long as necessary, in my case as long as the variable a.
In your case, since the returns of arraymap::map are not assigned to variables, they are temporary values and they are quickly dropped. But even if you assigned it to a local variable, you could not return a reference to it, because the local variable is dropped when the function ends.
The solution is to return an iterator that owns the value. Something like this works:
type IntegerCycle = Cycle<std::vec::IntoIter<i32>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let cycles = [
[1, 2],
[2, 4],
];
cycles
.map(|points| {
points.map(|point| point*2)
})
.map(|points| {
points.to_vec().into_iter().cycle()
})
}
Unfortunately you have to use a Vec instead of an array, because there is not an IntoIterator implementation for arrays, (there are for slices, but they do not own the values).
If you want to avoid the extra allocation of Vec you can use the arrayvec crate that does allow to take an iterator to an array:
type IntegerCycle = Cycle<arrayvec::IntoIter<[i32; 2]>>;
fn generate_cycles() -> [IntegerCycle; 2] {
let cycles = [
[1, 2],
[2, 4],
];
cycles
.map(|points| {
points.map(|point| point*2)
})
.map(|points| {
let a = arrayvec::ArrayVec::from(*points);
a.into_iter().cycle()
})
}
NOTE: It looks like there is an attempt to add a proper IntoIterator impl for arrays by value to the std, but there are still some pending issues.
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]);