I'm learning F# and get stuck with the concept of mutable keyword.
Please see the below example:
let count =
let mutable a = 1
fun () -> a <- a + 1; a
val count: unit -> int
Which increases by 1 every time it's called with (). But next code does not:
let count =
let mutable a = 1
a <- a + 1
a
val count: int
Which is always 2.
In the book I'm studying with, it says with the first example, "The initialization of mutable value a is done only once, when the function has called first time."
When I started learning FP with haskell, the way it handled side effects like this totally burnt my brain, but F# mutable is destroying my brain again, with a different way. What's the difference between above two snippets? And, what's the true meaning and condition of above sentence, about the initialization of mutable value?
Your second example
let count =
let mutable a = 1
a <- a + 1
a
Defines a mutable variable initialised to 1, then assigns a new value (a + 1) to it using the <- operator before returning the updated value on the last line. Since a has type int and this is returned from the function the return type of the function is also int.
The first example
let count =
let mutable a = 1
fun () -> a <- a + 1; a
also declares an int a initialised to 1. However instead of returning it directly it returns a function which closes over a. Each time this function is called, a is incremented and the updated value returned. It could be equivalently written as:
let count =
let mutable a = 1
let update () =
a <- a + 1
a
update
fun () -> ... defines a lambda expression. This version returns a 1-argument function reflected in the different return type of unit -> int.
The first example of count initializes a mutable variable, and returns a closure around this variable. Every time you call that closure, the variable is increased, and its new value returned.
The second example of count is just an initialization block that sets the variable, increases it once, and returns its value. Referring to count again only returns the already computed value again.
Related
I know there are several related question and moreover I can find many posts in the Internet.
However, I can't understand the fact that closures can hold references. In case of a reference type, it is totally usual and very reasonable, but how about a value type, including struct and enum?
See this code.
let counter: () -> Int
var count = 0
do {
counter = {
count += 1
return count
}
}
count += 1 // 1
counter() // 2
counter() // 3
We can access the value type count through two ways. One is by using count directly and the another is through the closure counter.
However, if we write
let a = 0
let b = a
, in the memory b has of course a different area with a because they are value type. And this behavior is a distinct feature of value type which is different with reference type.
And then backing to the closure topic, closure has the reference to value type's variable or constant.
So, can I say the value type's feature that we can't have any references to value type is changed in case of closure's capturing values?
To me, capturing references to value type is very surprising and at the same time the experience I showed above indicates that.
Could you explain this thing?
I think the confusion is by thinking too hard about value types vs reference types. This has very little to do with that. Let's make number be reference types:
class RefInt: CustomStringConvertible {
let value: Int
init(value: Int) { self.value = value }
var description: String { return "\(value)" }
}
let counter: () -> RefInt
var count = RefInt(value: 0)
do {
counter = {
count = RefInt(value: count.value + 1)
return count
}
}
count = RefInt(value: count.value + 1) // 1
counter() // 2
counter() // 3
Does this feel different in any way? I hope not. It's the same thing, just in references. This isn't a value/reference thing.
The point is that, as you note, the closure captures the variable. Not the value of the variable, or the value of the reference the variable points to, but the variable itself). So changes to the variable inside the closure are seen in all other places that have captured that variable (including the caller). This is discussed a bit more fully in Capturing Values.
A bit deeper if you're interested (now I'm getting into a bit of technicalities that may be beyond what you care about right now):
Closures actually have a reference to the variable, and changes they make immediately occur, including calling didSet, etc. This is not the same as inout parameters, which assign the value to their original context only when they return. You can see that this way:
let counter: () -> Int
var count = 0 {
didSet { print("set count") }
}
do {
counter = {
count += 1
print("incremented count")
return count
}
}
func increaseCount(count: inout Int) {
count += 1
print("increased Count")
}
print("1")
count += 1 // 1
print("2")
counter() // 2
print("3")
counter() // 3
increaseCount(count: &count)
This prints:
1
set count
2
set count
incremented count
3
set count
incremented count
increased Count
set count
Note how "set count" is always before "incremented count" but is after "increased count." This drives home that closures really are referring to the same variable (not value or reference; variable) that they captured, and why we call it "capturing" for closures, as opposed to "passing" to functions. (You can also "pass" to closures of course, in which case they behave exactly like functions on those parameters.)
If I have a square grid (created in WPF/XAML) in any size, with a given number of cells per side, it should be ridiculously easy to calculate the coordinates to a cell that was clicked by getting the mouse cursor position relative to the grid element. As I try to learn F#, I experience some problems with the syntax and would appreciate some input.
Here is an example of what I am trying to do:
// From a mouse event, fetch the position of the cursor relative to a IInputElement
let get_mouse_position (relative_to : IInputElement) (args : Input.MouseEventArgs) : (int*int) =
let position = args.GetPosition relative_to
((Convert.ToInt32(position.X) / cellsPerSide), (Convert.ToInt32(position.Y) / cellsPerSide))
// Get the position of the cursor relative to the grid
let get_cell_coordinates (element : IInputElement) =
get_mouse_position element
However, when I try to use the coordinates retrieved by calling get_cell_coordinates somewhere else where (x,y) coordinates are needed, I get an error that says:
This expression was expected to have type int * int but here has type 'a -> int * int
So, what am I doing wrong and why do I get this polymorph type and not just a tuple of integers?
The type you got is not a "polymorph" type, it's a function type. The reason you got a function of type 'a -> int * int instead of the int * int result you were expecting is because you didn't pass all the parameters to your function, so F# returned a function that expected the rest of the parameters. This is called "partial application", and you can read more about it here:
https://fsharpforfunandprofit.com/posts/currying/
and
https://fsharpforfunandprofit.com/posts/partial-application/
A quick summary of the two articles: in F#, all functions are treated as taking one parameter and returning one result. Yes, ALL functions. When you create a function that appears to take two parameters, F# rewrites it internally. It becomes a function that takes one parameter and returns a second function; this second function takes one parameter and returns the result. A concrete example will probably be useful at this point. Consider this function:
let doubleAndSubtract a b = (a * 2) - b
(Obviously, the parentheses around a * 2 aren't actually needed, but I left them in to make the function unambiguous to read).
Internally, F# actually rewrites this function into the following:
let doubleAndSubtract a =
let subtract b = (a * 2) - b
subtract
In other words, it builds a function that "closes over" (captures) the value of a that you passed in. So the following two functions are completely equivalent:
let explicitSubtract b = (5 * 2) - b
let implicitSubtract = doubleAndSubtract 5
If you type these functions in to the F# interactive prompt and look at the types that it declares each function to have, explicitSubtract has type b:int -> int, and implicitSubtract has type int -> int. The only difference between these two is that the type of explicitSubtract names the parameter, whereas implicitSubtract doesn't "know" the name of its parameter. But both will take an int, and return an int (specifically, 10 minus the parameter).
Now, let's look at the type signature for doubleAndSubtract. If you typed it into the F# interactive prompt, you'll have seen that its type signature is int -> int -> int. In type signatures, -> is right-associative, so that signature is really int -> (int -> int) -- in other words, a function that takes an int and returns a function that takes an int and returns an int. But you can also think of it as a function that takes two ints and returns an int, and you can define it that way.
So, what happened with your code here is that you defined the function like this:
let get_mouse_position (relative_to : IInputElement) (args : Input.MouseEventArgs) : (int*int) = ...
This is a function that takes two parameters (of types IInputElement and Input.MouseEventArgs) and returns a tuple of ints... but that's equivalent to a function that takes one parameter of type IInputElement, and returns a function that takes an Input.MouseEventArgs and returns a tuple of two ints. In other words, your function signature is:
IInputElement -> Input.MouseEventArgs -> (int * int)
When you called it as get_mouse_position element you passed it only a single parameter, so what you got was a function of type Input.MouseEventArgs -> (int * int). The type checker reported this as type 'a -> int * int (changing Input.MouseEventArgs into the generic type name 'a) for reasons I don't want to get into here (this is already rather long), but that's why you got the result you got.
I hope this helps you understand F# functions better. And do read those two articles I linked to; they'll take your understanding another step further.
I solved it by using the static Mouse.GetPosition method to obtain the position of the mouse instead of Input.MouseEventArgs.
The code now looks as follows, if anyone else has the same problem:
// From a mouse event, fetch the position of the cursor relative to a IInputElement
let get_mouse_position (relative_to : IInputElement) : (int*int) =
let position = Mouse.GetPosition relative_to
((Convert.ToInt32(position.X) / cellsPerSide), (Convert.ToInt32(position.Y) / 32))
// Get the position of the cursor relative to the input element
let get_cell_coordinates (element : IInputElement) =
get_mouse_position element
In FSI I type
> let a = 10;;
val a : int = 10
> let a = a + 1;;
val a : int = 11
Looks like I have a mutable variable here? Am I missing something?
It is not a mutable value. But you use the shadowing : in F#, value shadowing occurs when a variable declared within a certain scope (decision block, method, or inner class) has the same name as a variable declared in an outer scope.
If you want to have a mutable value, there is a syntaxe in F# :
let mutable a = 10
a <- a + 1
As already explained by Arthur, what you see is shadowing which means that the original "variable" named a is hidden by a new "variable" also named a (I use variable in quotes, because they are actually immutable values).
To see the difference, you can capture the original value in a function and then print the value after hiding the original value:
> let a = 10;; // Define the original 'a' value
val a : int = 10
> let f () = a;; // A function captures the original value
val f : unit -> int
> let a = 42;; // Define a new value hiding the first 'a'
val a : int = 42
> f();; // Prints the original value - it is not mutated!
val it : int = 10
Sadly, you cannot use exactly the same code to see how let mutable behaves (because F# does not allow capturing mutable references in closures), but you can see mutation when you use reference cells (that is, a simple object that stores mutable value in the heap):
> let a = ref 10;; // Create a mutable reference cell initialized to 10
val a : int ref = {contents = 10;}
> let f () = !a;; // A function reads the current value of the cell
val f : unit -> int
> a := 42;; // Overwrite the value in the cell with 42
val it : unit = ()
> f();; // Prints the new value - it is mutated
val it : int = 42
You can run the code line-by-line in F# interactive, but it will do exactly the same thing when you copy the entire snippet (the input lines) and place them in normal F# code - e.g. inside a function or a module. The ;; is just to end the line in the F# interactive input (I typed the code in the F# Interactive window), but it is not needed in normal code, because F# uses indentation to find out where a statement ends.
Why is disabled types like
type t = A of int | B of string * mutable int
while such types are allowed:
type t = A of int | B of string * int ref
The question is, how would you modify the value of a mutable element of discriminated union case? For ref types, this is quite easy, because ref is a reference cell (a record actually) which contains the mutable value:
match tval with
| B(str, refNum) -> refNum := 4
We extract the reference cell and assign it to a new symbol (or a new variable) refNum. Then we modify the value inside the ref cell, which also modifies tval, because the two references to the cell (from discriminated union case and from refNum variable) are aliased.
On the other hand, when you write let mutable n = 0, you're creating a variable, which can be directly mutated, but there is no cell holding the mutable value - the variable n is directly mutable. This shows the difference:
let mutable a = 10
let mutable b = a
b <- 5 // a = 10, b = 5
let a = ref 10
let b = a
b := 5 // a = 5, b = 5 (because of aliasing!)
So, to answer your question - there is no way to directly refer to the value stored inside the discriminated union case. You can only extract it using pattern matching, but that copies the value to a new variable. This means that there isn't any way you could modify the mutable value.
EDIT
To demonstrate limitations of mutable values in F#, here is one more example - you cannot capture mutable values inside a closure:
let foo() =
let mutable n = 0
(fun () -> n <- n + 1; n) // error FS0407
I think the reason is same as with discriminated union cases (even though it's not as obvious in this case). The compiler needs to copy the variable - it is stored as a local variable and as a field in the generated closure. And when copying, you want to modify the same variable from multiple references, so aliasing semantics is the only reasonable thing to do...
Ref is a type (int ref = ref<int>). Mutable is not a type, it's a keyword that allows you to update a value.
Example:
let (bla:ref<int>) = ref 0 //yup
let (bla:mutable<int>) = 3 //no!
I am attempting to write some simple code in F#, and i get this error:
Error 1 The mutable variable 'i' is used in an invalid way. Mutable variables may not be captured by closures. Consider eliminating this use of mutation or using a heap-allocated mutable reference cell via 'ref' and '!'
Code:
let printProcess = async {
let mutable i = 1;
while true do
System.Console.WriteLine(i);//error is here
i <- i + 1;
}
Why won't it let me print the variable?
You can't refer to mutables inside a closure, and that includes such constructs as seq{} and async{} blocks.
You could write
let printProcess = async {
let i = ref 1
while true do
System.Console.WriteLine(!i)
i := !i + 1
}
See this blog for some discussion.