I was taught, that data, by default, is immutable in F#.
When we reassign value to some variable, what really happens is that it rebinds the value of variable, but setting a new value is different thing.
Rebinding is called Shadowing whilst setting new value is impossible if we don't say explicitly, that value of the variable is mutable.
Can anyone explain to me this concept in a bit more details?
What is the difference between shadowing (rebinding):
let var = "new_value"
and setting a new value, as:
var <- "new_value"
Is this a moment, that during rebinding we create another object and we assign that object's address to the variable, whereas in the second example we change the value itself? I brought that from heap/stack concept.. but I may be wrong.
Thanks.
Shadowing is when you create a new binding that uses the same name as a previous binding. This "shadows" the original name, which hides it but doesn't change or replace it. Try this in FSI to see:
let foo = 42
let printFoo () =
printfn "%i" foo
printFoo() ;;
This will print:
42
val foo : int = 42
val printFoo : unit -> unit
val it : unit = ()
Then add:
// ... more code
let foo = 24
printfn "%i" foo // prints 24
printFoo ();;
This will print:
24
42
val foo : int = 24
val it : unit = ()
Note that it still prints 42 when you call printFoo() - the function sees the original (unshadowed) binding, but the new print shows the new value.
Using <- to mutate a value requires a mutable binding:
let mutable bar = 42
let printBar () =
printfn "%i" bar
printBar ();;
This, like above, prints 42. Note that you override the default immutable behavior here with the mutable keyword.
You then change the value within the mutable binding:
bar <- 24
printfn "%i" bar
printBar ();;
This will print 24 twice, since, unlike the shadowed version, the mutation changes the original binding. If you leave mutable off in the original binding, you'll get an error when using <-.
To add on Reed Copsey's excellent answer, if you're writing a loop where you change the value of an accumulator of some sort, you'd set the original value as mutable. For example, you can do this.
let mutable acc = 0 // declaration
for i in 1..100 do
acc <- acc + i // assignment
This is more or less equivalent to the C# code :
var acc = 0;
for (int i = 1; i <= 100; i++)
{
acc = acc + i; // assignment
// Another way to write this:
// acc += i;
}
However, in Shadowing, as in this F# snippet:
let acc = 0 // declaration
for i in 1..100 do
let acc = acc + i // another declaration only within the loop
You're not actually doing anything useful!! The second declaration has scope only within the for loop, and it doesn't change the value of the original acc.
A rough C# equivalent would be this:
var acc = 0; // declaration
for (int i = 1; i <= 100; i++)
{
var acc2 = acc + i; // another declaration only within the loop
}
Note that using acc (instead of acc2) for the inside variable wouldn't compile in C#, as it doesn't have Shadowing in this context.
The use of shadowing is that, it prevents from using the original variant in a block of code where you don't want it. So there is one less variable to worry about.
Whenever I wonder what actually is happening I use tools like ILSpy
For example:
let f () =
let x = Dictionary<int, string> ()
let mutable x = ResizeArray<int> 16
x <- ResizeArray<int> 16
Using ILSpy to decompile it in C# code it becomes:
public static void f()
{
Dictionary<int, string> x = new Dictionary<int, string>();
List<int> x2 = new List<int>(16);
x2 = new List<int>(16);
}
Here it's more obvious what the difference between shadowing and setting.
Shadowing x creates a new variable with name x2.
Setting is normal assignment.
Related
Sorry for my question but I did not understand the answers that was related to this question so I hope someone can enlighten me further.
I am a new data science student and we are going to learn how to program in the functional language F#. We are learning about algorithms and I wanted to write the algorithms as F# functions to check if my calculations on paper were correct.
I get the following error saying:
"This value is not mutable. Consider using the mutable keyword let mutable n = expression"
My code looks like this:
let loop5( n ) =
let mutable x = 0
while n > 0 do
x <- x + 1
n <- n + 1
printfn "loop5(): x=%i for n=%i" x n
loop5(4)
I'm trying to write a function looking like this (pseudocode):
loop5(n)
x = 0
while n > 0
x = x + 1
n = n + 1
return x
Hope I made a clear question and someone can help me out here :-) Have a nice weekend
You're trying to mutate the loop's parameter n. The parameter is not mutable, so the compiler doesn't let you. That's exactly what the error tells you.
Now, normally, to make the error go away, you'd make the variable mutable. However, you can't make a function parameter mutable, so that's not an option.
Here you want to think what the meaning of your program should be. Does the loop function need to pass the updated value of n back to its caller, or is the whole mutation its internal business? If it's the former, please see #AnyMoose's answer, but from your example and explanation, I suspect it's the latter. If that is the case, simply make a mutable copy of the parameter and work with it:
let loop n' =
let mutable x = 0
let mutable n = n'
...
Separately, I want to point out that your program, as written, would actually loop indefinitely (or until it wraps around the max int value anyway), because instead of decreasing n at each step you're increasing it. If you want your program to actually finish before the next Ice Age, you need to make n decrease with each iteration:
n <- n - 1
Ref cells
Ref cells get around some of the limitations of mutables. In fact, ref cells are very simple datatypes which wrap up a mutable field in a record type. Ref cells are defined by F# as follows:
type 'a ref = { mutable contents : 'a }
The F# library contains several built-in functions and operators for working with ref cells:
let ref v = { contents = v } (* val ref : 'a -> 'a ref *)
let (!) r = r.contents (* val (!) : 'a ref -> 'a *)
let (:=) r v = r.contents <- v (* val (:=) : 'a ref -> 'a -> unit *)
The ref function is used to create a ref cell, the ! operator is used to read the contents of a ref cell, and the := operator is used to assign a ref cell a new value. Here is a sample in fsi:
let x = ref "hello";;
val x : string ref
x;; (* returns ref instance *)
val it : string ref = {contents = "hello";}
!x;; (* returns x.contents *)
val it : string = "hello"
x := "world";; (* updates x.contents with a new value *)
val it : unit = ()
!x;; (* returns x.contents *)
val it : string = "world"
Since ref cells are allocated on the heap, they can be shared across multiple functions:
open System
let withSideEffects x =
x := "assigned from withSideEffects function"
let refTest() =
let msg = ref "hello"
printfn "%s" !msg
let setMsg() =
msg := "world"
setMsg()
printfn "%s" !msg
withSideEffects msg
printfn "%s" !msg
let main() =
refTest()
Console.ReadKey(true) |> ignore
main()
The withSideEffects function has the type val withSideEffects : string ref -> unit.
This program outputs the following:
hello
world
Assigned from withSideEffects function
The withSideEffects function is named as such because it has a side-effect, meaning it can change the state of a variable in other functions. Ref Cells should be treated like fire. Use it cautiously when it is absolutely necessary but avoid it in general. If you find yourself using Ref Cells while translating code from C/C++, then ignore efficiency for a while and see if you can get away without Ref Cells or at worst using mutable. You would often stumble upon a more elegant and more maintanable algorithm
Aliasing Ref Cells
Note: While imperative programming uses aliasing extensively, this practice has a number of problems. In particular it makes programs hard to follow since the state of any variable can be modified at any point elsewhere in an application. Additionally, multithreaded applications sharing mutable state are difficult to reason about since one thread can potentially change the state of a variable in another thread, which can result in a number of subtle errors related to race conditions and dead locks.
A ref cell is very similar to a C or C++ pointer. Its possible to point to two or more ref cells to the same memory address; changes at that memory address will change the state of all ref cells pointing to it. Conceptually, this process looks like this:
Let's say we have 3 ref cells looking at the same address in memory:
Three references to an integer with value 7
cell1, cell2, and cell3 are all pointing to the same address in memory. The .contents property of each cell is 7. Let's say, at some point in our program, we execute the code cell1 := 10, this changes the value in memory to the following:
Three references to an integer with value 10
By assigning cell1.contents a new value, the variables cell2 and cell3 were changed as well. This can be demonstrated using fsi as follows:
let cell1 = ref 7;;
val cell1 : int ref
let cell2 = cell1;;
val cell2 : int ref
let cell3 = cell2;;
val cell3 : int ref
!cell1;;
val it : int = 7
!cell2;;
val it : int = 7
!cell3;;
val it : int = 7
cell1 := 10;;
val it : unit = ()
!cell1;;
val it : int = 10
!cell2;;
val it : int = 10
!cell3;;
val it : int = 10
I would like to have a mutable state in an F# object expression.
The first approach is to use ref cells as follows:
type PP =
abstract member A : int
let foo =
let a = ref 0
{ new PP with
member x.A =
let ret = !a
a := !a + 1
ret
}
printfn "%A" foo.A
printfn "%A" foo.A
printfn "%A" foo.A
printfn "%A" foo.A
A different approach would be as follows:
type State(s : int) =
let mutable intState = s
member x.state
with get () = intState
and set v = intState <- v
[<AbstractClass>]
type PPP(state : State) =
abstract member A : int
member x.state
with get () = state.state
and set v = state.state <- v
let bar n =
{ new PPP(State(n)) with
member x.A =
let ret = x.state
x.state <- ret + 1
ret
}
let barA1 = bar 0
printfn "%A" barA1.A
printfn "%A" barA1.A
printfn "%A" barA1.A
printfn "%A" barA1.A
Which version would be likely more performing (I need the state updating x.state <- ret + 1
in performance critical sections)? My guess is that the State object is also allocated on the heap so there is no reason why the second version should be faster. However it is slightly more appealing to use.
Thanks for any feedback and suggestions
As Daniel said, the last approach is essentially equivalent to using built-in ref.
When using ref, you're allocating two objects - the one that you're returning and the reference cell itself. You can reduce this to just a single allocated object by using a concrete implementation (but I don't think this will matter in practice):
type Stateful(initial:int) =
let mutable state = initial
interface PP with
member x.A =
let ret = state
state <- state + 1
ret
let foo =
Statefull(0) :> PP // Creates a single object that keeps the state as mutable field
Aside, you are using read-only property that modifies internal state of the object and returns a new state each time. This is a dangerous pattern that could be quite confusing - properties with getter shouldn't modify the state, so you should probably use a method (unit -> int) instead.
Your State class is identical to ref. They're both reference types (you can't capture a mutable value type from an object expression). I would prefer a built-in type when possible. ref is the idiomatic way to represent a heap-allocated mutable value.
If ever in doubt about performance, benchmark it.
Is there a way to have mutable function arguments in F#, that would allow something like
let mutable i = 9
let somefun n = n <- 12; ()
somefun i
(* *not* a real-world example *)
I do understand that this can be made to work by wrapping it into a record type
type SomeRec = { mutable i: int }
let ri = { i = 9 }
let someotherfun r = r.i <- 12; ()
and that this can be done in a similar fashion for class members. However, even after browsing through the whole F# Language Specification (yes, I did!), there seems to be no syntax to allow the first case, and the compiler appears to be quite unhappy about my trying this. I was hoping there would be some sort of type annotation, but mutable cannot be used in such.
I also know that I should not be doing this sort of thing in the first place, but the first case (int binding) and the second (record type) are semantically identical, and any such objection would hold for both cases equally.
So I think that I am missing something here.
You can use ref as arguments
let v = ref 0
let mutate r =
r := 100
mutate v
printfn "%d" !v
Or byref keyword
let mutable v = 0
let mutate (r : byref<_>) =
r <- 100
mutate &v
printfn "%d" v
Use byref keyword which is equivalent to C# ref.
See Passing by reference.
What would be an elegant way to implement the functionality of this nested class in F#?
private class Aliaser {
private int _count;
internal Aliaser() { }
internal string GetNextAlias() {
return "t" + (_count++).ToString();
}
}
This was my first attempt, but it feels like there should be a sexy one-liner for this:
let aliases = (Seq.initInfinite (sprintf "t%d")).GetEnumerator()
let getNextAlias() =
aliases.MoveNext() |> ignore
aliases.Current
The usual way of writing is to create a function with local state captured in a closure:
let getNextAlias =
let count = ref 0
(fun () ->
count := !count + 1;
sprintf "t%d" (!count))
The type of getNextAlias is simply unit -> string and when you call it repeatedly, it returns strings "t1", "t2", ... This relies on mutable state, but the mutable state is hidden from the user.
Regarding whether you can do this without mutable state - the simple answer is NO, because when you call a purely functional function with the same parameter twice, it must return the same result. Thus, you'd have to write something with the following structure:
let alias, state1 = getNextAlias state0
printf "first alias %s" alias
let alias, state2 = getNextAlias state1
printf "second alias %s" alias
// ...
As you can see, you'd need to keep some state and maintain it through the whole code. In F#, the standard way of dealing with this is to use mutable state. In Haskell, you could use State monad, which allows you to hide the passing of the state. Using the implementation from this question, you could write something like:
let getNextAlias = state {
let! n = getState
do! setState (n + 1)
return sprintf "t%d" n }
let program =
state {
let! alias1 = getNextAlias()
let! alias2 = getNextAlias()
// ...
}
execute progam 0 // execute with initial state
This is quite similar to other computations such as lazy or seq, actually - computations in the state { .. } block have some state and you can execute them by providing initial value of the state. However, unless you have good reasons for requiring purely functional solution, I'd prefer the first version for practical F# programming.
Here is the quick and dirty translation
type Aliaser () =
let mutable _count = 0
member x.GetNextAlias() =
let value = _count.ToString()
_count <- _count + 1
"t" + value
A more functional approach without state is to use continuations.
let createAliaser callWithValue =
let rec inner count =
let value = "t" + (count.ToString())
callWithValue value (fun () -> inner (count + 1))
inner 1
This is a declaration which will call the function callWithValue with both the value and the function to execute to repeat with the next value.
And here's an example using it
let main () =
let inner value (next : unit -> unit )=
printfn "Value: %s" value
let input = System.Console.ReadLine()
if input <> "quit" then next()
createAliaser inner
main()
I would use Seq.unfold : (('a -> ('b * 'a) option) -> 'a -> seq<'b>) to generate the aliases.
Implemented as:
let alias =
Seq.unfold (fun count -> Some(sprintf "t%i" count, count+1)) 0
Is it possible to call a method on a returned object using the pipeline infix operator?
Example, I have a .Net class (Class1) with a method (Method1). I can currently code it like this:
let myclass = new Class1()
let val = myclass.Method1()
I know I could also code it as such
let val = new Class1().Method1()
However I would like to do be able to pipeline it (I am using the ? below where I don't know what to do):
new Class1()
|> ?.Method1()
Furthermore, say I had a method which returns an object, and I want to only reference it if that method didn't return null (otherwise bail?)
new Class1()
|> ?.Method1()
|> ?? ?.Method2()
Or to make it clearer, here is some C# code:
public void foo()
{
var myclass = new Class1();
Class2 class2 = myclass.Method1();
if (class2 == null)
{
return;
}
class2.Method2();
}
You can define something similar to your (??) operator fairly easily (but operators can't start with a question mark):
let (~??) f x =
if (x <> null) then
f x
Unfortunately, your pipelined code will need to be a bit more verbose (also, note that you can drop the new keyword for calling constructors):
Class1()
|> fun x -> x.Method1()
Putting it all together:
Class1()
|> fun x -> x.Method1()
|> ~?? (fun x -> x.Method2())
Using a custom operator as 'kvb' suggests is definitely an option. Another approach that you may find interesting in this case is to define your own 'computation expression' that automatically performs the check for null value at every point you specify. The code that uses it would look like this:
open System.Windows.Forms
// this function returns (0) null, or (1) btn whose parent is
// null or (2) button whose parent is not null
let test = function
| 1 -> new Button(Text = "Button")
| 2 -> new Button(Text = "Button", Parent = new Button(Text = "Parent"))
| _ -> null
let res =
safe { let! btn = test(2) // specify number here for testing
// if btn = null, this part of the computation will not execute
// and the computation expression immediately returns null
printfn "Text = %s" btn.Text
let! parent = btn.Parent // safe access to parent
printfn "Parent = %s" parent.Text // will never be null!
return parent }
As you can see, when you want to use a value that can potentially be 'null', you use let! inside the computation expression. The computation expression can be defined so that it immediately returns null if the value is null and runs the rest of the computation otherwise. Here is the code:
type SafeNullBuilder() =
member x.Return(v) = v
member x.Bind(v, f) =
if v = null then null else f(v)
let safe = new SafeNullBuilder()
BTW: If you want to learn more about this, it is very similar to 'Maybe' monad in Haskell (or computation working with F# option type).