Scope confusion in F# - scope

Let's consider this code:
type TypeA =
{
A : int
}
type TypeB =
{
B : float
}
module Test =
let mutable c : TypeA = { A = 0 }
module Test2 =
let mutable c : TypeB = { B = 0 }
it produces the error:
typecheck error This expression was expected to have type
'float'
but here has type
'int'
What I do not understand is why there is a collision between the two variables 'c'.
They have different scopes:
type TypeA =
{
A : int
}
module Test =
let mutable c : TypeA = { A = 0 }
module Test2 =
let mutable c : TypeA = { A = 0 }
with
Test.c <- { A = 1 }
Test2.c <- { A = 2 }
Test.c, Test2.c
gives
{ FSI_0009+TypeA: A: 1 } { FSI_0009+TypeA: A: 2 }
Can someone explain why there is this error?

There is no collision between two variables c - they are defined in separate modules. F# just cannot implicitly convet integer literal 0 to float. Use 0.0 or 0. in the second case:
let mutable c : TypeB = { B = 0.0 }
Also, F# type inference is smart enough to infer that the first variable c has type TypeA, and the second variable c has type TypeB (because record labels are different) so you can even remove type annotations here:
module Test =
let mutable c = { A = 0 } // TypeA inferred
module Test2 =
let mutable c = { B = 0. } // TypeB inferred

Related

Specify type of numeric literal as `type` alias

I would like to write the equivalent of 2_u32, 7_i64, etc but where the numeric type is given by a type alias. e.g.,
type Number = u32;
fn main() {
let a = 1_Number; // invalid syntax
let b = 1_u32; // works, but isn't tied to `Number`
let c = 1 as Number; // equivalent to `1_i32 as Number`, which is not what I want
let d = Number::from(1) // requires `Number: From<i32>`, again not what I want
let e = ???
}
So, is there a way to write “variable” numeric literal, whose type is that of a given type alias?
You can use type annotations:
let a: Number = 1;
Or, for inside nested expressions, you can create a macro to do that for you:
macro_rules! force_type {
($v:expr, $ty:ty $(,)?) => {{
let v: $ty = $v;
v
}};
}
foo(force_type!(1, Number));
If you can limit yourself to literals, you can use a nicer syntax:
macro_rules! n {
($v:literal : $ty:ty) => {{
let v: $ty = $v;
v
}}
}
foo(n!(1: Number));

Initialize variable based on enum

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

Calculating prime numbers in Rust

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
}

Associated constants in condition of constant ìf`-expression

I am trying to use associated constants as a condition in an if-expression to initialize another constant. I think that this should work, as I can use the associated constants directly to initialize some other constant, so it is applicable in a const context and the if expression does not depend on any other values.
trait C {
const c: i32;
}
trait StaticAssert<T1: C, T2: C> {
const canUseAssociatedConst: i32 = T1::c;
const canCompareAssociatedConst: bool = T1::c == T2::c;
const check: i32 = if T1::c == T2::c { 1 } else { 0 };
}
When I compile this, I get an error:
error[E0019]: constant contains unimplemented expression type
--> src/lib.rs:9:24
|
9 | const check: i32 = if T1::c == T2::c { 1 } else { 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I am not sure what the compiler wants to tell me. I've added i32 suffixes to enforce that the literals are actually i32 values to prevent any issues from different types in the branches, but this did not help either.
As far as I know, if and others are not (yet) supported in const contexts.
However, often you can acchieve a similar effect along the lines of the following:
trait C {
const c: i32;
}
trait StaticAssert<T1:C, T2:C> {
const canUseAssociatedConst: i32 = T1::c;
const canCompareAssociatedConst: bool = T1::c == T2::c;
const check: i32 = (T1::c == T2::c) as i32;
}

return a recursive closure which move environmental mutable variable into it from a function?

Ways that make recursive closure are not suitable for me from the accepted answer of the question:
Is it possible to make a recursive closure in Rust?
My closure need to be returned from a function and need to move variable from the environment into it, and can mutate it.
Then I find a way seems more suitable for me:
Anonymous recursion with closures
use std::cell::RefCell;
fn main() {
let id = &(|a| a) as &Fn(u64) -> u64;
let (fib, fib_p): (_, RefCell<&Fn(u64) -> u64>);
fib_p = RefCell::new(id);
fib = |n: u64| {
if n < 2 {
n
} else {
(fib_p.borrow())(n - 2) + (fib_p.borrow())(n - 1)
}
};
*fib_p.borrow_mut() = &fib;
println!("{}", fib(10));
}
The above code works fine.
But my closure need to be returned from a function, so it can't be a reference to prevent dangling Reference, and we don't know the size of the closure from compile time, so I used the smart pointer Box for it. The below code throws an error:
use std::cell::RefCell;
fn main() {
let id: Box<Fn(u64) -> u64> = Box::new(|a| a);
let (fib, fib_p): (Box<Fn(u64) -> u64>, RefCell<&Box<Fn(u64) -> u64>>);
fib_p = RefCell::new(&id);
fib = Box::new(|n: u64| {
if n < 2 {
n
} else {
(fib_p.borrow())(n - 2) + (fib_p.borrow())(n - 1)
}
});
*fib_p.borrow_mut() = &fib;
println!("{}", fib(10));
}
error[E0597]: `fib_p` does not live long enough
--> src/main.rs:12:15
|
8 | fib = Box::new(|n: u64| {
| -------- capture occurs here
...
12 | (&fib_p.borrow())(n - 2) + (&fib_p.borrow())(n - 1)
| ^^^^^ borrowed value does not live long enough
...
19 | }
| - borrowed value dropped before borrower
|
= note: values in a scope are dropped in the opposite order they are created
You can wrap your recursive context in a non recursive closure:
pub fn fib() -> Box<Fn(u64) -> u64> {
Box::new(|n: u64| {
let id = &(|a| a) as &Fn(u64) -> u64;
let (fib, fib_p): (_, RefCell<&Fn(u64) -> u64>);
fib_p = RefCell::new(id);
fib = |n: u64| {
if n < 2 {
n
} else {
(fib_p.borrow())(n - 2) + (fib_p.borrow())(n - 1)
}
};
*fib_p.borrow_mut() = &fib;
fib(n)
})
}

Resources