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.
Related
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.
I want to write a parser.
It seems practical to me to have a mutable Iterator that I can pass around to different parser functions.
I've tried to illustrated a simplified approach, which compiles but is not ideal yet.
fn main() {
let tokens = vec!["fIrSt".to_string(), "SeConD".to_string(), "tHiRd".to_string(), "FoUrTh".to_string()];
let parsed = parse_input(tokens);
println!("{}", parsed);
}
fn parse_input(tokens: Vec<String>) -> String {
let mut tokens_iter = tokens.iter();
let upps = parse_upper(&mut tokens_iter);
let lowers = parse_lower(&mut tokens_iter);
upps + &lowers
}
fn parse_upper(tokens_iter: &mut Iterator<Item=&String>) -> String {
let mut result = String::new();
let token_1 = tokens_iter.next().unwrap().to_uppercase();
let token_2 = tokens_iter.next().unwrap().to_uppercase();
result.push_str(&token_1);
result.push_str(&token_2);
result
}
fn parse_lower(tokens_iter: &mut Iterator<Item=&String>) -> String {
let mut result = String::new();
let token_1 = tokens_iter.next().unwrap().to_lowercase();
let token_2 = tokens_iter.next().unwrap().to_lowercase();
result.push_str(&token_1);
result.push_str(&token_2);
result
}
How the example works:
Let's say I have some input, that has already been tokenized. Here it is represented by the tokens vector (Vec<String>).
Inside the outer parse_input function, the Vec gets transformed into an Iterator and then passed into different, specific parser functions. Here: parse_upper and parse_lower. In real life those could be "parse_if_statement" or "parse_while_loop" but which part of the Iterator gets worked on is not relevant for the question.
What is relevant is, that every call to next advances the cursor on the Iterator. So that every function consumes the pieces it needs.
This example compiles and gives the output: FIRSTSECONDthirdfourth
I would like to be able to peek() into the Iterator, before I pass it to a function. This is necessary to determine which function should actually be called. But everything I have tried with using a Peekable instead of an Iterator resulted in total lifetime and borrow chaos.
Any suggestions on how to pass a Peekable instead of an Iterator in this case?
Maybe using a Peekable as function parameter is a bad idea in the first place. Or maybe my Iterator approach is already wrong. All suggestions/hints are welcome.
I am serializing two values in to an array and I am trying to go through a WriteBuf but I am getting the error that
error: the trait `std::io::Write` is not implemented for the type `[_; 12]`
error: type `std::io::buffered::BufWriter<&mut [_; 12]>` does not implement any method in scope named `write_be_u32`
error: type `std::io::buffered::BufWriter<&mut [_; 12]>` does not implement any method in scope named `write_be_f64`
Here is the minimum code to generate this error:
use std::io::{ BufWriter, Write };
fn main(){
let packed_data = [0; 12];
let timestamp : u32 = 100;
let value : f64 = 9.9;
let writer = BufWriter::new(&mut packed_data);
writer.write_be_u32(timestamp);
writer.write_be_f64(value);
println!("Packed data looks like {:?}", packed_data);
}
Am I no borrowing the slice correctly? Am I note using the proper module to define the Write trait for my buffer?
Here is a playpen for this code: http://is.gd/ol8qND
I see a few potential problems with your code:
packed_data isn't mutable.
You use packed_data at the end of main while writer holds a mutable reference to it.
I don't think that either of those things are causing the error. I did however find something that works:
use std::io::{ BufWriter, Write };
fn main() {
let mut packed_data = [0; 12];
{
let packed_data_ref: &mut [u8] = &mut packed_data;
let mut writer = BufWriter::new(packed_data_ref);
writer.write(&[1, 2, 3, 4]).unwrap();
} // `writer` gets deallocated and releases the mutable reference
println!("Packed data looks like {:?}", packed_data);
}
[playpen]
So I guess the issue is that you need a &[u8] rather than a &[u8; 12]. I have no idea why. I hope this at least helps though.
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!