Rust: Error[E0277]: the trait bound `{integer}: SampleRange<_>` is not satisfied - rust

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

Related

Convert for loop to iterator in rust

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.

String incrementer problem using rust (codewars)

im trying to solve the string incrementer problem which is in codewars using rust
https://www.codewars.com/kata/54a91a4883a7de5d7800009c/train/rust
but when i wrote this code and ran . it came a error
error[E0599]: the method `to_string` exists for struct `Chars<'_>`, but its trait bounds were not satisfied
--> src/lib.rs:2:29
|
2 | let mut num = s.chars().to_string().filter(|c| "0123456789".contains(c)).collect();
| ^^^^^^^^^ method cannot be called on `Chars<'_>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`Chars<'_>: std::fmt::Display`
which is required by `Chars<'_>: ToString`
error[E0599]: no method named `remove_last` found for reference `&str` in the current scope
--> src/lib.rs:4:11
|
4 | s.remove_last();
the real code is
fn increment_string(s: &str) -> String {
let mut num = s.chars().to_string().filter(|c| "0123456789".contains(c)).collect();
for i in 1..=num.len(){
s.remove_last();
}
num = num.chars().map(|c| c.parse::<u32>().unwrap()) + 1;
format!("{}{}",s,num);
}
can someone help me to rectify this error ?
Instead of let mut num = s.chars().to_string().filter(|c| "0123456789".contains(c)).collect(); you can write let mut num: String = s.chars().filter(|c| c.is_numeric()).collect();.
.pop() is used for removing the last element from the String
you don't need ; at the end of the function
Here is the working code (I've tested it on a few cases): https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=35d48393fa8ece9a2bb4cdc5c6544fcd
But you can still optimize it, I suppose ;)

error[E0597]: borrowed value does not live long enough in While loop

I am really new to Rust, I am having trouble solving this error, but it only happens if I comment out the while statement , basicly I am asking values from the console and storing it in a HashMap:
use std::collections::HashMap;
use std::io;
fn main() {
let mut customers = HashMap::new();
let mut next_customer = true;
while next_customer {
let mut input_string = String::new();
let mut temp_vec = Vec::with_capacity(3);
let mut vec = Vec::with_capacity(2);
println!("Insert new customer f.e = customer id,name,address:");
io::stdin().read_line(&mut input_string);
input_string = input_string.trim().to_string();
for s in input_string.split(",") {
temp_vec.push(s);
}
vec.push(temp_vec[1]);
vec.push(temp_vec[2]);
let mut key_value = temp_vec[0].parse::<i32>().unwrap();
customers.insert(key_value, vec);
next_customer = false;
}
println!("DONE");
}
The code results in the error
error[E0597]: `input_string` does not live long enough
--> src/main.rs:14:18
|
14 | for s in input_string.split(",") {
| ^^^^^^^^^^^^ borrowed value does not live long enough
...
20 | customers.insert(key_value, vec);
| --------- borrow later used here
21 | next_customer = false;
22 | }
| - `input_string` dropped here while still borrowed
As others have said the problem lies with the lifetime and/or type of the values getting put into the customers map.
customers.insert(key_value, vec);
| --------- borrow later used here
Often this happens when the compiler has decided to give an object a type that you didn't expect. To find out what it's doing you can force the type, and see how it complains. Changing the code to:
let mut customers: HashMap<(),()> = HashMap::new();
Gives us two relevant errors:
20 | customers.insert(key_value, vec);
| ^^^^^^^^^ expected `()`, found `i32`
...
20 | customers.insert(key_value, vec);
| ^^^ expected `()`, found struct `std::vec::Vec`
|
= note: expected unit type `()`
found struct `std::vec::Vec<&str>`
So the type that the compiler wants to give our customers object is HashMap<i32, Vec<&str>>
The problem is that the &str lifetime has got to be inside the block as we don't store the Strings anywhere, and they can't have 'static lifetime since they're user input.
This means we probably want a HashMap<i32,Vec<String>>.
Changing the code to use one of those gives us an error about vec not having the right type: It's getting deduced as a Vec<&str>, but we want a Vec<String>.
We have two options.
Convert the vec to the right type just before we insert it into the map using customers.insert(key_value, vec.iter().map(|s| s.to_string()).collect()). (Though you may want to extract it to a variable for clarity).
Explicitly change the type of vec to Vec<String>
Option 1 "just works". While option 2 leads us down a path of making similar changes closer and closer to the read_line call.
Once you've decided on the fix in option 1, you can remove the manual type annotations that were added to work out the fix, if you find them overly noisy.
The issue is that you are passing around reference to underlying &str values that will get dropped. One way is to take the input string, trim and split it, then clone it going into the other vector.
let temp_vec: Vec<String> = input_string.trim().split(",").map(|t| t.to_string()).collect();
vec.push(temp_vec[1].clone());
vec.push(temp_vec[2].clone());

Why can't I collect the Lines iterator into a vector of Strings?

I'm trying to read the lines of a text file into a vector of Strings so I can continually loop over them and write each line to a channel for testing, but the compiler complains about collect:
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::path::Path;
fn main() {
let file = File::open(Path::new("file")).unwrap();
let reader = BufReader::new(&file);
let _: Vec<String> = reader.lines().collect().unwrap();
}
The compiler complains:
error[E0282]: type annotations needed
--> src/main.rs:9:30
|
9 | let lines: Vec<String> = reader.lines().collect().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `B`
|
= note: type must be known at this point
Without the .unwrap(), compiler says:
error[E0277]: a collection of type `std::vec::Vec<std::string::String>` cannot be built from an iterator over elements of type `std::result::Result<std::string::String, std::io::Error>`
--> src/main.rs:9:45
|
9 | let lines: Vec<String> = reader.lines().collect();
| ^^^^^^^ a collection of type `std::vec::Vec<std::string::String>` cannot be built from `std::iter::Iterator<Item=std::result::Result<std::string::String, std::io::Error>>`
|
= help: the trait `std::iter::FromIterator<std::result::Result<std::string::String, std::io::Error>>` is not implemented for `std::vec::Vec<std::string::String>`
How do I tell Rust the correct type?
Since you want to collect straight into a Vec<String> while the Lines iterator is over Result<String, std::io::Error>, you need to help the type inference a little bit:
let lines: Vec<String> = reader.lines().collect::<Result<_, _>>().unwrap();
or even just:
let lines: Vec<_> = reader.lines().collect::<Result<_, _>>().unwrap();
This way the compiler knows that there is an intermediate step with a Result<Vec<String>, io::Error>. I think this case could be improved in the future, but for now the type inference is not able to deduce this.

How do I parse a vector into a function?

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]) {

Resources