So, I am trying to build a vector of vectors of a custom type.I am trying to implement a default for it and was successful with a for loop.
let mut data: Vec<Vec<Cell>> = Vec::new();
for _i in 0..63 {
let mut row: Vec<Cell> = Vec::with_capacity(64);
for _j in 0..63 {
row.push(Cell::default())
}
data.push(row);
}
I felt this code could do with some functional style and interators, so I decided to do something like so:
let data: Vec<Vec<Cell>> = Vec::with_capacity(64)
.iter_mut()
.map(|mut x: &mut Vec<Cell>| {
x = Vec::with_capacity(64)
.iter_mut()
.map(|mut y: Cell| y = Cell::default())
.collect()
})
.collect();
With this, I get an error like so:
error[E0631]: type mismatch in closure arguments
--> src/types.rs:124:26
|
124 | .map(|mut y: Cell| y = Cell::default())
| ^^^ ------------- found signature defined here
| |
| expected due to this
|
= note: expected closure signature `fn(&mut _) -> _`
found closure signature `fn(types::cell::Cell) -> _`
note: required by a bound in `map`
--> /home/naitik/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:779:12
|
779 | F: FnMut(Self::Item) -> B,
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
I do not understand the problem here. What exactly is it? What can I do to fix it?
You're misunderstanding how Vec::with_capacity works. It doesn't actually put anything into a vec that you can iterate over and assign to. You want to map Cell::default over something and then collect that into a vec. That something doesn't matter, only that there's 64 of them, so a range will do:
let data: Vec<Vec<Cell>> = (0..64)
.map(|_| (0..64).map(|_| Cell::default()).collect())
.collect();
collect should hopefully figure out the needed capacities from the ranges' TrustedLen impl on its own to avoid unnecessary re-allocations.
I would, however, doubt that this is better than the procedural approach. It seems less clear and harder to modify to me. Just stick to good ol' for loops is my two cents.
If Cell is Clone or Copy you could even just do:
let data: Vec<Vec<Cell>> = vec![vec![Cell::default(); 64]; 64];
for maximal minimality.
Related
I am looping loop over a Vec<&str>, each time reassigning a variable that holds the intersection of the last two checked. This is resulting in "expected char, found &char". I think this is happening because the loop is a new block scope, which means the values from the original HashSet are borrowed, and go into the new HashSet as borrowed. Unfortunately, the type checker doesn't like that. How do I create a new HashSet<char> instead of HashSet<&char>?
Here is my code:
use std::collections::HashSet;
fn find_item_in_common(sacks: Vec::<&str>) -> char {
let mut item: Option<char> = None;
let mut sacks_iter = sacks.iter();
let matching_chars = sacks_iter.next().unwrap().chars().collect::<HashSet<_>>();
loop {
let next_sack = sacks_iter.next();
if next_sack.is_none() { break; }
let next_sack_values: HashSet<_> = next_sack.unwrap().chars().collect();
matching_chars = matching_chars.intersection(&next_sack_values).collect::<HashSet<_>>();
}
matching_chars.drain().nth(0).unwrap()
}
and here are the errors that I'm seeing:
error[E0308]: mismatched types
--> src/bin/03.rs:13:26
|
6 | let matching_chars = sacks_iter.next().unwrap().chars().collect::<HashSet<_>>();
| ---------------------------------------------------------- expected due to this value
...
13 | matching_chars = matching_chars.intersection(&next_sack_values).collect::<HashSet<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `char`, found `&char`
|
= note: expected struct `HashSet<char>`
found struct `HashSet<&char>`
By the way, what is that first error trying to tell me? It seems like it is missing something before or after "expected" -- <missing thing?> expected <or missing thing?> due to this value?
I also tried changing matching_chars = matching_chars to matching_chars = matching_chars.cloned() and I get the following error. I understand what the error is saying, but I don't know how to resolve it.
error[E0599]: the method `cloned` exists for struct `HashSet<char>`, but its trait bounds were not satisfied
--> src/bin/03.rs:13:41
|
13 | matching_chars = matching_chars.cloned().intersection(&next_sack_values).collect::<HashSet<_>>();
| ^^^^^^ method cannot be called on `HashSet<char>` due to unsatisfied trait bounds
|
::: /Users/brandoncc/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/collections/hash/set.rs:112:1
|
112 | pub struct HashSet<T, S = RandomState> {
| -------------------------------------- doesn't satisfy `HashSet<char>: Iterator`
|
= note: the following trait bounds were not satisfied:
`HashSet<char>: Iterator`
which is required by `&mut HashSet<char>: Iterator`
Your attempt at using cloned() was almost right but you have to call it after you create the iterator:
matching_chars.intersection(&next_sack_values).cloned().collect::<HashSet<_>>()
or for Copy types you should use the more appropriate .copied() adapter:
matching_chars.intersection(&next_sack_values).copied().collect::<HashSet<_>>()
Looking at the signature of HashSet::intersection will make this clearer:
pub fn intersection<'a>(
&'a self,
other: &'a HashSet<T, S>
) -> Intersection<'a, T, S>
The type Intersection<'a, T, S> implements Iterator<Item=&'a T>. So when you collect this iterator, you get a HashSet<&char> as opposed to a HashSet<char>.
The solution is simply to use .cloned on the iterator before you use .collect, since char is Clone, like so:
matching_chars = matching_chars.intersection(&next_sack_values).cloned().collect()
By the way, what is that first error trying to tell me?
The error is telling you that it expects char because (due to) the original value for matching_chars has type HashSet<char>.
I also tried changing matching_chars = matching_chars to matching_chars = matching_chars.cloned() and I get the following error. I understand what the error is saying, but I don't know how to resolve it.
Do you, really?
str::chars is an Iterator<Item=char>, so when you collect() to a hashset you get a HashSet<char>.
The problem is that intersection borrows the hashset, and since the items the hashset contains may or may not be Clone, it also has to borrow the set items, it can't just copy or clone them (not without restricting its flexibility anyway).
So that's where you need to add the cloned call, on the HashSet::intersection in order to adapt it from an Iterator<Item=&char> to an Iterator<Item=char>.
Or you can just use the & operator, which takes two borrowed hashsets and returns an owned hashset (requiring that the items be Clone).
Alternatively use Iterator::filter or Iterator::findon one of the sets, checking if the othersHashSet::containsthe item being looked at. Fundamentally that's basically whatintersection` does, and you know there's just one item at the end.
This code draws four red dots in a picture.
use plotters::chart::{DualCoordChartContext, ChartContext, SeriesAnno};
use plotters::coord::types::RangedCoordf32;
use plotters::prelude::*;
use plotters::coord::Shift;
type CC<'a> = ChartContext<'a, BitMapBackend<'a>, Cartesian2d<RangedCoordf32, RangedCoordf32>>;
//type CCBAD = ChartContext<BitMapBackend, Cartesian2d<RangedCoordf32, RangedCoordf32>>;
const OUT_FILE_NAME: &'static str = "sample.png";
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let root_area: DrawingArea<BitMapBackend, Shift> =
BitMapBackend::new(OUT_FILE_NAME, (400, 400)).into_drawing_area();
let mut cb: ChartBuilder<BitMapBackend> =
ChartBuilder::on(&root_area);
let mut cc: ChartContext<BitMapBackend, Cartesian2d<RangedCoordf32, RangedCoordf32>> =
cb.build_cartesian_2d(0.0f32..5.0f32, 0.0f32..5.0f32)?;
let series: Vec<f32> = vec![1.0, 2.0, 3.0, 4.0];
cc.draw_series(PointSeries::of_element(
series.iter().map(|x| (*x, *x)), 3,ShapeStyle::from(&RED).filled(),
&|coord, size, style| { EmptyElement::at(coord) + Circle::new((0, 0), size, style) },
))?;
Ok(())
}
I put the explicit types of variables on purpose (because why not?).
Soo... the types seem a bit long. How about we make shorter names.
Let's start with ChartContext. The compiler only lets me make the type type CC<'a>. CCBAD has missing lifetimes.
But if I try to use it like this:
let mut cc: CC = // ChartContext<BitMapBackend, Cartesian2d<RangedCoordf32, RangedCoordf32>> =
cb.build_cartesian_2d(0.0f32..5.0f32, 0.0f32..5.0f32)?;
It's suddenly a problem! Why?
16 | ChartBuilder::on(&root_area);
| ^^^^^^^^^^ borrowed value does not live long enough
...
25 | }
| -
| |
| `root_area` dropped here while still borrowed
| borrow might be used here, when `root_area` is dropped and runs the destructor for type `plotters::drawing::DrawingArea<plotters::prelude::BitMapBackend<'_>, Shift>`
Another story is trying to put the "draw_series" call into a function. Basically it ends up with the same error message as here.
Why I can specify the type ChartContext<BitMapBackend, Cartesian2d<RangedCoordf32, RangedCoordf32>> but cannot make a 'type' definition with it. Why that weird error?
By reusing the same lifetime twice you're forcing 2 lifetimes to be the same that shouldn't be.
Use this instead:
type CC<'a, 'b> = ChartContext<'a, BitMapBackend<'b>, Cartesian2d<RangedCoordf32, RangedCoordf32>>;
I have a line of code that is in a for loop, and it's supposed to generate a random number from 0 to 2499. It is giving me problems.
let index = rand::thread_rng().gen_range(2499);
Full code for those who want to know:
fn generate_phrase () -> String {
let mut phrase = String::new();
let mut file = File::open("words.txt").expect("Failed to open words.txt");
let mut contents = String::new();
file.read_to_string(&mut contents).expect("Failed to read words.txt");
let words: Vec<&str> = contents.split("\n").collect();
for _ in 0..8 {
let index = rand::thread_rng().gen_range(2499);
phrase.push_str(words[index]);
phrase.push(' ');
}
println!("Your phrase is: {:?}", phrase);
return phrase;
}
Error message:
error[E0277]: the trait bound `{integer}: SampleRange<_>` is not satisfied
--> src/crypto/crypto.rs:115:45
|
115 | let index = rand::thread_rng().gen_range(2499);
| --------- ^^^^ the trait `SampleRange<_>` is not implemented for `{integer}`
| |
| required by a bound introduced by this call
|
note: required by a bound in `gen_range`
--> C:\Users\Administrator\.cargo\registry\src\github.com-1ecc6299db9ec823\rand-0.8.5\src\rng.rs:132:12
|
132 | R: SampleRange<T>
| ^^^^^^^^^^^^^^ required by this bound in `gen_range
I know the problem, which is that the trait is not the right kind but I don't know how to convert the integer into the necessary trait: SampleRange<T>. I've looked on StackOverFlow and couldn't find an appropriate answer anywhere.
The SampleRange that it complains about can be either a Range or RangeInclusive, rather than just an upper-bound (see the "implementations" section in SampleRange to see which types implement the trait). All you need is to change that one line to look something like this:
let index = rand::thread_rng().gen_range(0..2499);
The idea is to send a set of characters of a vector and let the function display the current correct guesses.
Here is my main:
fn main() {
let mut guessedLetters = vec![];
displayWord(guessedLetters);
}
And here is the function:
fn displayWord(correctGuess: Vec<char>) {
let mut currentWord = String::new();
for x in 0..5 {
currentWord.push(correctGuess[x]);
}
println!("Current guesses: {}", currentWord);
}
I don't know what I'm supposed to write inside the parameters of displayWord.
There's a couple of things wrong with your code.
The first error is pretty straight forward:
--> src/main.rs:38:25
|
38 | displayWord(guessed_Letters);
| ^^^^^^^^^^^^^^^ expected char, found enum `std::option::Option`
|
= note: expected type `std::vec::Vec<char>`
found type `std::vec::Vec<std::option::Option<char>>`
The function you wrote is expecting a vector a characters ... but you're passing it a vector of Option<char>. This is happening here:
guessed_Letters.push(line.chars().nth(0));
According to the documentation, the nth method returns an Option. The quick fix here is to unwrap the Option to get the underlying value:
guessed_Letters.push(line.chars().nth(0).unwrap());
Your next error is:
error[E0382]: use of moved value: `guessed_Letters`
--> src/main.rs:38:25
|
38 | displayWord(guessed_Letters);
| ^^^^^^^^^^^^^^^ value moved here in previous iteration of loop
|
= note: move occurs because `guessed_Letters` has type `std::vec::Vec<char>`, which does not implement the `Copy` trait
This is transferring ownership of the vector on the first iteration of the loop and the compiler is telling you that subsequent iterations would be in violation of Rust's ownership rules.
The solution here is to pass the vector by reference instead:
displayWord(&guessed_Letters);
..and your method should also accept a reference:
fn displayWord(correctGuess: &Vec<char>) {
let mut currentWord = String::new();
for x in 0..5 {
currentWord.push(correctGuess[x]);
}
println!("Current guesses: {}", currentWord);
}
This can be shortened to use a slice and still work:
fn displayWord(correctGuess: &[char]) {
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).