I am trying to calculate prime numbers in Rust but having some issues. I getting two errors. I am not understanding how the value is returning to the main function.
fn main() {
let x = is_prime(25); //function calling
println!("{}", x);
}
fn is_prime(n: u32) -> bool {
let mut result: bool = for a in 2..n {
result = if n % a == 0 { false } else { true };
};
result
}
error[E0425]: cannot find value `result` in this scope
--> src/main.rs:8:9
|
8 | result = if n % a == 0 { false } else { true };
| ^^^^^^ not found in this scope
help: possible candidates are found in other modules, you can import them into scope
|
1 | use futures::future::result;
|
1 | use tokio::prelude::future::result;
|
error[E0308]: mismatched types
--> src/main.rs:7:28
|
6 | fn is_prime(n: u32) -> bool {
| ---- expected `bool` because of return type
7 | let mut result: bool = for a in 2..n {
| ____________________________^
8 | | result = if n % a == 0 { false } else { true };
9 | | };
| |_____^ expected bool, found ()
|
= note: expected type `bool`
found type `()`
The problem with your code is that you are using the variable result while defining it
...
let mut result: bool = for a in 2..n { // declared here
result = if n % a == 0 { // used here, but it is still not initialized
...
You can easily do without the result variable, is not necessary:
fn is_prime(n: u32) -> bool {
if n <= 1 {
return false;
}
for a in 2..n {
if n % a == 0 {
return false; // if it is not the last statement you need to use `return`
}
}
true // last value to return
}
Playground link
You have several issues in your code (ignoring that it does not compile):
you overwrite the result -> imagine n = 4. When you divide by 2 you get result = true, but in the next iteration when you divide by 3 you get result = false
if n<=2 your loop will never be executed, hence what will result be
Instead of trying to use any new piece of syntax, try to write it to be as readable as possible:
fn is_prime(n: u32) -> bool {
let limit = (n as f64).sqrt() as u32;
for i in 2..=limit {
if n % i == 0 {
return false;
}
}
true
}
Related
I'm trying to learn Rust after many years of C++. I have a situation where the compiler is complaining about a borrow, and it doesn't seem to matter whether it is mutable or immutable. I don't seem to be able to use self as a parameter inside a loop that start with: for item in self.func.drain(..).I've tried calling appropriate() as a function:
Self::appropriate(&self,&item,index)
and I have tried it as a method:
self.appropriate(&item,index)
but I get the same message in either case:
The function or method appropriate() is intended imply examine the relationship among its parameters and return a bool without modifying anything. How can I call either a function or method on self without violating borrowing rules?This program is a learning exercise from exercism.org and doesn't include a main() so it won't run but should almost compile except for the error in question. Here's the code I have:
use std::collections::HashMap;
pub type Value = i32;
pub type Result = std::result::Result<(), Error>;
pub struct Forth {
v: Vec<Value>,
f: HashMap<String,usize>,
s: Vec<Vec<String>>,
func: Vec<String>
}
#[derive(Debug, PartialEq)]
pub enum Error {
DivisionByZero,
StackUnderflow,
UnknownWord,
InvalidWord,
}
impl Forth {
pub fn new() -> Forth {
let mut temp: Vec<Vec<String>> = Vec::new();
temp.push(Vec::new());
Forth{v: Vec::<Value>::new(), f: HashMap::new(), s: temp, func: Vec::new()}
}
pub fn stack(&self) -> &[Value] {
&self.v
}
pub fn eval(&mut self, input: &str) -> Result {
self.v.clear();
self.s[0].clear();
let mut count = 0;
{
let temp: Vec<&str> = input.split(' ').collect();
let n = temp.len() as i32;
for x in 0..n as usize {
self.s[0].push(String::from(temp[x]));
}
}
let mut collecting = false;
let mut xlist: Vec<(usize,usize)> = Vec::new();
let mut sx: usize = 0;
let mut z: i32 = -1;
let mut x: usize;
let mut n: usize = self.s[0].len();
loop {
count += 1;
if count > 20 {break;}
z += 1;
x = z as usize;
if x >= n {break;}
z = x as i32;
let word = &self.s[sx][x];
if word == ";" {
if collecting {
collecting = false;
let index: usize = self.s.len();
self.s.push(Vec::<String>::new());
for item in self.func.drain(..) {
if self.s[index].len() > 0 &&
Self::appropriate(&self,&item,index)
{
let sx = *self.f.get(&self.s[index][0]).unwrap();
let n = self.s[sx].len();
for x in 1..n as usize {
let symbol = self.s[sx][x].clone();
self.s[index].push(symbol);
}
}
else {
self.s[index].push(item);
}
}
self.f.insert(self.s[index][0].clone(), index);
self.func.clear();
continue;
}
if 0 < xlist.len() {
(x, n) = xlist.pop().unwrap();
continue;
}
return Err(Error::InvalidWord);
}
if collecting {
self.func.push(String::from(word));
continue;
}
if Self::is_op(word) {
if self.v.len() < 2 {
return Err(Error::StackUnderflow);
}
let b = self.v.pop().unwrap();
let a = self.v.pop().unwrap();
let c = match word.as_str() {
"+" => a + b,
"-" => a - b,
"*" => a * b,
"/" => {if b == 0 {return Err(Error::DivisionByZero);} a / b},
_ => 0
};
self.v.push(c);
continue;
}
match word.parse::<Value>() {
Ok(value) => { self.v.push(value); continue;},
_ => {}
}
if word == ":" {
collecting = true;
self.func.clear();
continue;
}
if word == "drop" {
if self.v.len() < 1 {
return Err(Error::StackUnderflow);
}
self.v.pop();
continue;
}
if word == "dup" {
if self.v.len() < 1 {
return Err(Error::StackUnderflow);
}
let temp = self.v[self.v.len() - 1];
self.v.push(temp);
continue;
}
if !self.f.contains_key(word) {
return Err(Error::UnknownWord);
}
xlist.push((sx,n));
sx = *self.f.get(word).unwrap();
n = self.s[sx].len();
z = 0;
}
Ok(())
}
fn is_op(input: &str) -> bool {
match input {"+"|"-"|"*"|"/" => true, _ => false}
}
fn appropriate(&self, item:&str, index:usize) -> bool
{
false
}
fn prev_def_is_short(&self, index: usize) -> bool {
if index >= self.s.len() {
false
}
else {
if let Some(&sx) = self.f.get(&self.func[0]) {
self.s[sx].len() == 2
}
else {
false
}
}
}
}
The error message relates to the call to appropriate(). I haven't even written the body of that function yet; I'd like to get the parameters right first. The compiler's complaint is:
As a subroutine call
error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable
--> src/lib.rs:85:47
|
81 | for item in self.func.drain(..) {
| -------------------
| |
| mutable borrow occurs here
| mutable borrow later used here
...
85 | Self::appropriate(&self,&item,index)
| ^^^^^ immutable borrow occurs here
For more information about this error, try `rustc --explain E0502`.
as a method call
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/lib.rs:85:29
|
81 | for item in self.func.drain(..) {
| -------------------
| |
| mutable borrow occurs here
| mutable borrow later used here
...
85 | self.appropriate(&item,index)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow occurs here
For more information about this error, try `rustc --explain E0502`.
Is there any canonical way to deal with this situation?
The problem is that self.func.drain() will consume the elements contained in self.func, thus an exclusive (&mut) access is needed on self.func for the entire for loop.
If during the iteration you need to pass a reference to self globally, then its func member is potentially accessible while the loop holds an exclusive access to it: Rust forbids that.
Since you use drain() in order to consume all the elements inside self.func, I suggest you swap this vector with an empty one just before the loop, then iterate on this other vector that is not anymore part of self.
No copy of the content of the vector is involved here; swap() only deals with pointers.
Here is an over-simplified version of your code, adapted consequently.
struct Forth {
func: Vec<String>,
}
impl Forth {
fn eval(&mut self) {
/*
for item in self.func.drain(..) {
self.appropriate(&self);
}
*/
let mut func = Vec::new();
std::mem::swap(&mut self.func, &mut func);
for item in func.drain(..) {
let b = self.appropriate();
println!("{:?} {:?}", item, b);
}
}
fn appropriate(&self) -> bool {
false
}
}
fn main() {
let mut f = Forth {
func: vec!["aaa".into(), "bbb".into()],
};
f.eval();
}
I have an enum:
enum DaEnum{
One(u8),
Strang(String),
}
I would like to variable y to be assigned value from enum:
let x = DaEnum::One(1);
let y;
match x{
DaEnum::One(one) => {y = one},
DaEnum::Strang(strang) => {y = strang},
}
println!("Value of y =>{:?}",y);
Here is the error from cargo run:
error[E0308]: mismatched types
--> src\main.rs:33:40
|
30 | let y;
| - expected due to the type of this binding
...
33 | DaEnum::Strang(strang) => {y = strang},
| ^^^^^^ expected `u8`, found struct `String`
Desired case would be when x is 1, y is 1and when x is a String, y would also be a String.
A generic function may help with your case if it's simple enough. You can pick up all the common behavior into one function and invoke it in every match arm. Please be aware of the trait because it must be shared by all your usages.
#[derive(Clone)]
enum DaEnum {
One(u8),
Strang(String),
}
fn main() {
let x = DaEnum::One(1);
fn common_stuff<T: std::fmt::Debug>(v: T) {
// common stuff
println!("Value of y =>{:?}", v);
}
// (1)
match x.clone() {
DaEnum::One(one) => {
let y = one;
// not common stuff
common_stuff(y);
}
DaEnum::Strang(strang) => {
let y = strang;
// not common stuff
common_stuff(y);
}
}
// (2)
match x {
DaEnum::One(one) => common_stuff(one),
DaEnum::Strang(strang) => common_stuff(strang),
}
}
struct OverflowError {}
fn test_unwrap() -> Result<String, OverflowError> {
let a: Result<String, u8> = Err(100);
let a: String = a.unwrap_or_else(|err| {
if err < 100 {
String::from("Ok")
} else {
// I want to return from the function (not just the closure)
// This is compile error with error:
// "the ? operator can only be used in a closure that returns Result or Option"
Err(OverflowError {})?
}
});
Ok(a)
}
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
--> src/lib.rs:13:13
|
6 | let a: String = a.unwrap_or_else(|err| {
| ______________________________________-
7 | | if err < 100 {
8 | | String::from("Ok")
9 | | } else {
... |
13 | | Err(OverflowError {})?
| | ^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a closure that returns `std::string::String`
14 | | }
15 | | });
| |_____- this function should return `Result` or `Option` to accept `?`
|
= help: the trait `std::ops::Try` is not implemented for `std::string::String`
= note: required by `std::ops::Try::from_error`
It's the simplified version of my code. Basically inside the unwrap_or_else closure, there might be a conditional error (e.g. IOError). In such cases, I'd like to terminate the function early (using ?). But obviously it doesn't work since it is currently in a closure and the closure doesn't expect a Result type.
What's the best practice to handle this?
What you want is or_else():
struct OverflowError {}
fn test_unwrap() -> Result<String, OverflowError> {
let a: Result<String, u8> = Err(100);
let a: String = a.or_else(|err| {
if err < 100 {
Ok(String::from("Ok"))
} else {
Err(OverflowError {})
}
})?;
Ok(a)
}
Simplified:
struct OverflowError {}
fn test_unwrap() -> Result<String, OverflowError> {
Err(100).or_else(|err| {
if err < 100 {
Ok(String::from("Ok"))
} else {
Err(OverflowError {})
}
})
}
In a function that is declared to return bool:
pub fn is_palindrome(num: u64) -> bool {
let mut digits = Vec::new();
let mut temp = num;
loop {
digits.push(temp % 10);
temp /= 10;
if temp == 0 {
break;
}
}
for i in 0..digits.len() / 2 {
if digits[i] != digits[digits.len() - i] {
false // HERE I GET THE ERROR !!!!!!!
}
}
true
}
I get an error while compiling:
error[E0308]: mismatched types
--> src/lib.rs:13:13
|
13 | false
| ^^^^^ expected (), found bool
|
= note: expected type `()`
found type `bool`
Why is this happening, and how to fix the problem?
The issue is because you have an early return and not placing the return keyword before it, as shown below:
if digits[i] != digits[digits.len() - i] {
return false
}
This is because all functions evaluate the last line as a return value. If you want to return before going through the last line, you should add the return keyword.
An additional input here is to refactor your code so that it only returns once:
pub fn is_palindrome(num: u64) -> bool {
let mut digits = Vec::new();
let mut temp = num;
let mut retval = true;
loop {
digits.push(temp % 10);
temp /= 10;
if temp == 0 {
break;
}
}
for i in 0..digits.len() / 2 {
if digits[i] != digits[digits.len() - i] {
retval = false; // you might want to put a break here so that it exits the loop after finding the first issue
}
}
retval
}
I have two structs of the same type inside a larger struct. I will select one of the structs and perform updates using the same code.
A simplified version:
#[derive(Debug)]
struct Counts {
value: u16,
count: u8,
}
#[derive(Debug)]
struct Partitioned {
even: Counts,
odd: Counts,
}
fn sort() -> Partitioned {
let mut even = Counts { value: 2, count: 0 };
let mut odd = Counts { value: 3, count: 0 };
for i in 1..30 {
let mut s = if i % 2 == 0 { even } else { odd };
s.count = s.count + 1;
// ... a lot of other code
}
Partitioned { even, odd }
}
fn main() {
println!("{:?}", sort());
}
This does not compile with complaints about ownership:
error[E0382]: use of moved value: `even`
--> src/main.rs:19:37
|
19 | let mut s = if i % 2 == 0 { even } else { odd };
| ^^^^ value moved here in previous iteration of loop
|
= note: move occurs because `even` has type `Counts`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `odd`
--> src/main.rs:19:51
|
19 | let mut s = if i % 2 == 0 { even } else { odd };
| ^^^ value moved here in previous iteration of loop
|
= note: move occurs because `odd` has type `Counts`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `even`
--> src/main.rs:24:19
|
19 | let mut s = if i % 2 == 0 { even } else { odd };
| ---- value moved here
...
24 | Partitioned { even, odd }
| ^^^^ value used here after move
|
= note: move occurs because `even` has type `Counts`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `odd`
--> src/main.rs:24:25
|
19 | let mut s = if i % 2 == 0 { even } else { odd };
| --- value moved here
...
24 | Partitioned { even, odd }
| ^^^ value used here after move
|
= note: move occurs because `odd` has type `Counts`, which does not implement the `Copy` trait
What is going on here? How can I implement it without copying all the update code to both blocks of the if?
Take a mutable reference to the field:
let mut s = if i % 2 == 0 { &mut even } else { &mut odd };