What is the difference between a let-rebinding and a standard assignment? - binding

In Rust, in order to change the value of a mutable variable, what is the difference in let x = 12 or x = 12 in the following sample code?
fn main() {
let mut x: i32 = 8;
{
println!("{}", x);
let x = 12; // what if change to x = 12
println!("{}", x);
}
println!("{}", x);
let x = 42;
println!("{}", x);
}
The output is 8, 12, 8, 42. If I change let x = 12 to x = 12 ...
fn main() {
let mut x: i32 = 8;
{
println!("{}", x);
x = 12;
println!("{}", x);
}
println!("{}", x);
let x = 42;
println!("{}", x);
}
The output is 8, 12, 12, 42.
I understand that Rust uses let to do variable binding, so the let x = 12 is a variable rebinding and the binding is only valid inside a scope. But how to explain the functionality of x = 12 and the corresponding scope? Is that a type of variable binding?

The second let x introduces a second binding that shadows the first one for the rest of the block. That is, there are two variables named x, but you can only access the second one within the block statement after the let x = 12; statement. These two variables don't need to have the same type!
Then, after the block statement, the second x is out of scope, so you access the first x again.
However, if you write x = 12; instead, that's an assignment expression: the value in x is overwritten. This doesn't introduce a new variable, so the type of the value being assigned must be compatible with the variable's type.
This difference is important if you write a loop. For example, consider this function:
fn fibonacci(mut n: u32) -> u64 {
if n == 0 {
return 1;
}
let mut a = 1;
let mut b = 1;
loop {
if n == 1 {
return b;
}
let next = a + b;
a = b;
b = next;
n -= 1;
}
}
This function reassigns variables, so that each iteration of the loop can operate on the values assigned on the preceding iteration.
However, you might be tempted to write the loop like this:
loop {
if n == 1 {
return b;
}
let (a, b) = (b, a + b);
n -= 1;
}
This doesn't work, because the let statement introduces new variables, and these variables will go out of scope before the next iteration begins. On the next iteration, (b, a + b) will still use the original values.

Related

Functional digits reversion

In C, I would solve the problem with a loop. To represent the idea, something like:
void foo(int x){
while(x > 0){
printf("%d", x % 10);
x /= 10;
}
}
With F#, I am unable to make the function return the single values. I tried:
let reverse =
let aux =
fun x ->
x % 10
let rec aux2 =
fun x ->
if x = 0 then 0
else aux2(aux(x / 10))
aux2 n
but it returns always the base case 0.
I cannot get my mind beyond this approach, where the recursion results are maintained with an operation, and cannot be reported (according to may comprehension) individually:
let reverse2 =
let rec aux =
fun x ->
if x = 0 then 0
else (x % 10) + aux (x / 10) // The operation returning the result
aux n
This is a simple exercise I am doing in order to "functionalize" my mind. Hence, I am looking for an approach to this problem not involving library functions.
A for loop that changes the value of mutable variables can be rewritten as a recursive function. You can think of the mutable variables as implicit parameters to the function. So if we have a mutable variable x, we need to instead pass the new state of x explicitly as a function parameter. The closest equivalent to your C function as a recursive F# function is this:
let rec foo x =
if x > 0 then
printf "%d" (x % 10)
foo (x / 10)
This in itself isn't particularly functional because it returns unit and only has side effects. You can collect the result of each loop using another parameter. This is often called an accumulator:
let foo x =
let rec loop x acc =
if x > 0 then
loop (x / 10) (x % 10 :: acc)
else acc
loop x [] |> List.rev
foo 100 // [0; 0; 1]
I made an inner loop function that is actually the recursive one. The outer foo function starts off the inner loop with [] as the accumulator. Items are added to the start of the list during each iteration and the accumulator list is reversed at the end.
You can use another type as the accumulator, e.g. a string, and append to the string instead of adding items to the list.

Why does this definition returns a function?

I found the following in the book Expert F# 4.0, Fourth Edition, by Don Syme, Adam Granicz, and Antonio Cisternino:
let generateStamp =
let mutable count = 0
(fun () -> count <- count + 1; count)
I could not understand why this code creates a function:
val generateStamp : (unit -> int)
It looks to me like its signature should be
val generateStamp : int
For example, the following code:
let gS =
let mutable count = 0
(printfn "%d" count; count)
creates an int value:
val gS : int = 0
As I understand it the code (fun () -> count <- count + 1; count) should first evaluate the lambda and then count. So the value of generateStamp should be just count, as it is in the definition of gS. What am I missing?
In any block of F# code, the last expression in that block will be the value of that block. A block can be defined in one of two ways: by indentation, or with ; between the block's expressions.
The expression fun () -> other expressions here creates a function. Since that's the last expression in the code block under let generateStamp =, that's the value that gets stored in generateStamp.
Your confusion is that you think that the expressions inside the fun () are going to be evaluated immediately as part of the value of generateStamp, but they're not. They are defining the body of the anonymous function returned by the fun () expression. You're absolutely right that inside that block of code, count is the last expression and so it's the thing returned by that function. But the fun () expression creates a function, which will only evaluate its contents later when it is called. It does not evaluate its contents immediately.
By contrast, the expression (printfn "%d" count; count) is a block of code with two expressions in it. It is not a function, so it will be immediately evaluated. Its last expression is count, so the value of the code block (printfn "%d" count; count) is count. Since the (printfn "%d" count; count) block is being evaluated immediately, you can mentally replace it with count. And so the value of gS is count, whereas the value of generateStamp is a function that will return count when it's evaluated.
It's syntactic trickery. The last ; count part is actually part of the lambda, not the next expression after it.
Here are some simplified examples to work through:
let x = 1; 2; 3 // x = 3
let f x = 1; 2; 3 // f is a function
let y = f 5 // y = 3, result of calling function "f"
let f = fun x -> 1; 2; 3 // Equivalent to the previous definition of "f"
let y = f 5 // y = 3, same as above
let f =
fun x -> 1; 2; 3 // Still equivalent
let y = f 5 // y = 3, same as above
let f =
let z = 5
fun x -> 1; 2; 3 // Still equivalent
let y = f 5 // y = 3, same as above
// Your original example. See the similarity?
let generateStamp =
let mutable count = 0
fun () -> count <- count + 1; count
Now, if you wanted to have count be the return value of generateStamp, you'd need to put it either outside the parens or on the next line:
// The following two definitions will make "generateStamp" have type "int"
let generateStamp =
let mutable count = 0
(fun () -> count <- count + 1); count
let generateStamp =
let mutable count = 0
(fun () -> count <- count + 1)
count

How to set default argument value in F#?

Take this function as an example:
// Sequence of random numbers
open System
let randomSequence m n =
seq {
let rng = Random ()
while true do
yield rng.Next (m, n)
}
randomSequence 8 39
The randomSequence function takes two arguments: m, n. This works fine as a normal function. I would like to set the default for m, n, for example:
(m = 1, n = 100)
When there's no arguments given, the function take the default value. Is it possible in F#?
You can often achieve the same effect as overloading with a Discriminated Union.
Here's a suggestion based on the OP:
type Range = Default | Between of int * int
let randomSequence range =
let m, n =
match range with
| Default -> 1, 100
| Between (min, max) -> min, max
seq {
let rng = new Random()
while true do
yield rng.Next(m, n) }
Notice the introduction of the Range Discriminated Union.
Here are some (FSI) examples of usage:
> randomSequence (Between(8, 39)) |> Seq.take 10 |> Seq.toList;;
val it : int list = [11; 20; 36; 30; 35; 16; 38; 17; 9; 29]
> randomSequence Default |> Seq.take 10 |> Seq.toList;;
val it : int list = [98; 31; 29; 73; 3; 75; 17; 99; 36; 25]
Another option is to change the randomSequence ever so slightly to take a tuple instead of two values:
let randomSequence (m, n) =
seq {
let rng = new Random()
while true do
yield rng.Next(m, n) }
This would allow you to also define a default value, like this:
let DefaultRange = 1, 100
Here are some (FSI) examples of usage:
> randomSequence (8, 39) |> Seq.take 10 |> Seq.toList;;
val it : int list = [30; 37; 12; 32; 12; 33; 9; 23; 31; 32]
> randomSequence DefaultRange |> Seq.take 10 |> Seq.toList;;
val it : int list = [72; 2; 55; 88; 21; 96; 57; 46; 56; 7]
Optional parameters are permitted only on members [...]
https://msdn.microsoft.com/en-us/library/dd233213.aspx
So, for your current example, I think it is impossible.
But you could wrap the functionality:
type Random =
static member sequence(?m, ?n) =
let n = defaultArg n 100
let rng = new System.Random()
match m with
| None -> Seq.initInfinite (fun _ -> rng.Next(1, n))
| Some(m) -> Seq.initInfinite (fun _ -> rng.Next(m, n))
and then use it like this:
let randomSequence = Random.sequence(2, 3)
let randomSequence' = Random.sequence(n = 200)
let randomSequence'' = Random.sequence()
Explanation: optional parameters can either be fully Optional (m) or defaultArgs (n). I like shadowing (reusing the same name) these parameters, but that's debatable.
This seems to be the most elegant solution to this problem:
//define this helper function
let (|Default|) defaultValue input =
defaultArg input defaultValue
//then specify default parameters like this
let compile (Default true optimize) =
optimize
//or as the OP asks
let randomSequence (Default 1 m) (Default 100 n) =
seq {
let rng = new System.Random()
while true do
yield rng.Next(m,n)
}
Credits:
http://fssnip.net/5z
let randomSequence m n=
seq {
let rng = new Random()
while true do
yield rng.Next(m,n)
}
let randomSequenceWithDefaults() =
randomSequence 1 100
So instead, call randomSequenceWithDefaults()

immutable in F#

I know that variables in F# are immutable by default.
But, for example in F# interactive:
> let x = 4;;
val x : int = 4
> let x = 5;;
val x : int = 5
> x;;
val it : int = 5
>
So, I assign 4 to x, then 5 to x and it's changing. Is it correct? Should it give some error or warning? Or I just don't understand how it works?
When you write let x = 3, you are binding the identifier x to the value 3. If you do that a second time in the same scope, you are declaring a new identifier that hides the previous one since it has the same name.
Mutating a value in F# is done via the destructive update operator, <-. This will fail for immutable values, i.e.:
> let x = 3;;
val x : int = 3
> x <- 5;;
x <- 5;;
^^^^^^
stdin(2,1): error FS0027: This value is not mutable
To declare a mutable variable, add mutable after let:
let mutable x = 5;;
val mutable x : int = 5
> x <- 6;;
val it : unit = ()
> x;;
val it : int = 6
But what's the difference between the two, you might ask? An example may be enough:
let i = 0;
while i < 10 do
let i = i + 1
()
Despite the appearances, this is an infinite loop. The i declared inside the loop is a different i that hides the outer one. The outer one is immutable, so it always keeps its value 0 and the loop never ends. The correct way to write this is with a mutable variable:
let mutable i = 0;
while i < 10 do
i <- i + 1
()
x is not changed, it's just hidden by next declaration.
For example:
> let x = 4;;
val x : int = 4
> let x = "abc";;
val x : string = "abc"
>
You're not assigning 5 to x, you are defining a new variable.
The following example shows that there are two distinct variables.
(It also shows that you can "access" the old x if it is in a closure, used by another function):
let x = 5;;
let f y = y+x;;
f 10;;
let x = 0;;
f 10;;
yields
>
val x : int = 5
>
val f : int -> int
> val it : int = 15
>
val x : int = 0
> val it : int = 15
as you see, both calls to f use the first variable x. The definition let x = 0;; defines a new variable x, but does not redefines f.
Here's a minimal example illustrating identifier "shadowing" (i.e. hiding) in F#:
let x = 0
do //introduce a new lexical scope
let x = 1 //"shadow" (i.e. hide) the previous definition of x
printfn "%i" x //prints 1
//return to outer lexical scope
printfn "%i" x //prints 0, proving that our outer definition of x was not mutated by our inner definition of x
Your example is actually a bit more complex, because you are working in the F# Interactive (FSI). FSI dynamically emits code that looks something like the following in your example:
module FSI_0001 =
let x = 4;;
open FSI_0001 //x = 4 is now available in the top level scope
module FSI_0002 =
let x = 5;;
open FSI_0002 //x = 5 is now available in the top level scope, hiding x = 4
module FSI_0003 =
let it = x;;
open FSI_0003
//... subsequent interactions

f#: initialize array of array

in the following code, does array of array A = B?
let A = Array.init 3 (fun _ -> Array.init 2 (fun _ -> 0))
let defaultCreate n defaultValue = Array.init n (fun _ -> defaultValue)
let B = defaultCreate 3 (defaultCreate 2 0)
if I assign values to A and B, they are different ,what happened? thanks.
for i = 0 to 2 do
for j = 0 to 1 do
A.[i].[j] <-i + j
B.[i].[j] <-i + j
printfn "%A vs %A" A B
A = [|[|0; 1|]; [|1; 2|]; [|2; 3|]|] and B = [|[|2; 3|]; [|2; 3|]; [|2; 3|]|]
let B = defaultCreate 3 (defaultCreate 2 0)
You create an array and then you use this array as values for each cell.
It's as if you did something like this:
let a = [|1; 2; 3; 4|]
let b = [|a; a; a; a|]
The same array a is used for every cell (think pointer to a is you're used to C). Thus, modifying b.[0].[1] will change every a.[1].
In my sample:
> b.[0].[1] <- 10;;
val it : unit = ()
> b;;
[|[|1; 10; 3; 4|]; [|1; 10; 3; 4|]; [|1; 10; 3; 4|]; [|1; 10; 3; 4|]|]
The same thing happens with your code.
They are not the same.
Arrays are reference types, and are stored on the heap. When you create an array with another array as the default value, you are storing references to the same array, over and over again.
Numbers are another thing. They are immutable, and are stored by value, on the stack. So you can't change the value of 1 to anything other than 1.
To create an "jagged" array, you need to call Array.init from inside the initializer to the first Array.init call, to create new arrays for each slot.
Also; You could use Array.create if you do want to have the same value in every slot. Be careful about reference types though.
let A = Array.init 3 (fun _ -> Array.create 2 0)

Resources