with the simple case of, in C#:
i += 1;
how can I write this with a mutable in F#, other than:
i <- i + 1
is there a shorter syntax?
No, F# and Functional Programming in general discourage mutability. Thus the language doesn't make writing mutable code convenient.
If you love += you can create that operator by yourself:
let inline (+=) a b = a := !a + b
// test
let a = ref 100
a += 2
printfn "%d" !a // 102
You can check this article for more information about the Ref type.
AFAIK there's no built-in operator for increment mutables in place but there's a built-in function to increment int ref values.
let x = ref 0
incr x
printfn "%A" !x // ! dereferences an int ref
Related
I need help reversing bits in F# as done in this question Reverse bits in number. I'm new to F# and was wondering how we can do this?
let bitreverse x =
let mutable b = 0
while x do
b >>>= 1
b|= x & 1
x >>>= 1
b
I'm not even sure the syntax is correct here. I am very knew to this language.
The direct translation into F# looks like this:
let bitreverse x =
let mutable x = x
let mutable b = 0
while x <> 0 do
b <- b <<< 1
b <- b ||| (x &&& 1)
x <- x >>> 1
b
This is highly imperative with mutable values and this isn't usually how we'd tend to go about writing code in F#. Notice that re-assignment of a mutable variable is a little different to what you might be used to in an imperative language, you have to use <- which is called the destructive update operator.
Thankfully, it's pretty straightforward to translate this into a recursive function that uses immutable values which should be a little more idiomatic
let bitreverse2 x =
let rec bitRerverseHelper b x =
match x with
|0 -> b // if 0, the recursion stops here and we return the result: b
|_ -> bitRerverseHelper ((b <<< 1) ||| (x &&& 1)) (x >>> 1) // otherwise recurse
bitRerverseHelper 0 x
F# doesn't support compound assignment, so you can't do something like b |= x & 1, you need to expand it to b <- b ||| (x &&& 1).
The argument x isn't mutable, so you need to create a local binding and mutate that. It looks weird, but you can just write let mutable x = x as the first line of your function to shadow the existing binding with a mutable one.
x is an int, not a bool, so you can't use it as the condition for your while loop. Use x <> 0 instead.
Indentation matters in F#, so make sure that while and your final b both line up with the first let.
Fixing those issues will make your code work, but idiomatic F# would probably forgo the while loop and mutation and use a recursive inner function with an accumulator instead.
Maybe it's too simple thing to do, but I can't find any answer in the web
I'm try to Increment value in F# (like count++ in C#).
I don't want to use "mutable" option,
I'm just want to see an example, who Increment function in F# should look like.
And how do I use it.
The idea of "incrementing a value" in the same sense as in C++ only makes sense when you're working with mutable values or when you're using a mutable reference cell (essentially a simple object that stores a mutable value). If you have a mutable reference cell, you can use incr function:
let count = ref 0
incr count
If you use a mutable variable, then there is no built-in function for this and you need to write count + 1:
let mutable count = 0
count <- count + 1
If you're writing code using immutable values, then you will generally just write count + 1 and then pass the result to some function (or somewhere else - this depends on the specific case). For example, to calculate the length of an F# list, you would write:
let rec length list =
match list with
| [] -> 0
| _::tail -> 1 + (length tail)
In this example, the expression 1 + (...) is the code corresponding to i++ in a C++ code that iterates over a list and computes its length. The result of the expression is not assigned to a new variable, because it is returned directly as a result of the length function.
EDIT Parameters of functions are immutable meaning that you cannot change their values. As mentioned by Lee, you can use variable shadowing to hide the old value with a new one - but note that this only has a local effect (it is like defining a new variable with different name to store the new value). For example:
let rec length list count =
match list with
| [] -> count
| _::tail ->
let count = count + 1 // Variable shadowing used here
length tail count
You cannot write a function to simplify the line let count = count + 1 and as mentioned above, this is equivalent to writing let newCount = count + 1 and then using newCount on the last line.
You can't simulate a postincrement operator but you can do preincrement
let inline (+=) (x : byref<_>) y = x <- x + y
let mutable a = 0
&a += 1
or
let inline incv (x : byref<_>) = x <- x + LanguagePrimitives.GenericOne; x
let mutable b = 0
incv &b
If you don't want to use mutable then you can't really do a destructive update like ++ is in C#. You could shadow a variable with a new one with the same name e.g.
let x = 4;
let x = x + 1 in (x+4) //returns 8
although you couldn't write this as a function.
EDIT: If do want to use mutable variables then you can create a function which modifies a ref:
let increment (ir: int ref) = ir := !ir + 1
You can then use it as
let i = ref 1
increment i
let iv = !i //iv contains 2
As Tomas points out in his answer, this function already exists and is called incr.
I currently use this function
let inc (i : int ref) =
let res = !i
i := res + 1
res
to write things like
let str = input.[inc index]
How define increment operator ++, so that I could write
let str = input.[index++]
You cannot define postfix operators in F# - see 4.4 Operators and Precedence. If you agree to making it prefix instead, then you can define, for example,
let (++) x = incr x; !x
and use it as below:
let y = ref 1
(++) y;;
val y : int ref = {contents = 2;}
UPDATE: as fpessoa pointed out ++ cannot be used as a genuine prefix operator, indeed (see here and there for the rules upon characters and character sequences comprising valid F# prefix operators).
Interestingly, the unary + can be overloaded for the purpose:
let (~+) x = incr x; !x
allowing
let y = ref 1
+y;;
val y : int ref = {contents = 2;}
Nevertheless, it makes sense to mention that the idea of iterating an array like below
let v = [| 1..5 |]
let i = ref -1
v |> Seq.iter (fun _ -> printfn "%d" v.[+i])
for the sake of "readability" looks at least strange in comparison with the idiomatic functional manner
[|1..5|] |> Seq.iter (printfn "%d")
which some initiated already had expressed in comments to the original question.
I was trying to write it as a prefix operator as suggested, but you can't define (++) as a proper prefix operator, i.e., run things like ++y without the () as you could for example for (!+):
let (!+) (i : int ref) = incr i; !i
let v = [| 1..5 |]
let i = ref -1
[1..5] |> Seq.iter (fun _ -> printfn "%d" v.[!+i])
Sorry, but I guess the answer is that actually you can't do even that.
Consider the following code:
let mutable a = 0.
let b = ref 0.
a <- // works
printfn "%A" a
4. + 8.
b := // does not work
printfn "%A" a
4. + 8.
b := ( // works
printfn "%A" a
4. + 8. )
Why does the ref assignment operator (:=) have a different behaviour than the mutable assignment operator (<-)?
I can only give a partial answer.
:= is defined in terms of <- in FSharp.Core\prim-types.fs:
let (:=) x y = x.contents <- y
In your example
b := // does not work
printfn "%A" a
4. + 8.
printfn "%A" a seems to be interpreted as y, which cannot be assigned to the int ref cell (wrong type). By grouping the whole expression with ( ... ), y now also contains 4. + 8.. Maybe the two operators behave differently, because <- seems to be an intrinsic operator (i.e. part of the language, not the library).
Building on the other answers...
More elaborate expressions are allowed within assignments, so long as the final expression is one of several allowed forms. See section 6.4.9 of the spec. This allows complex assignments such as:
let x =
let rec gcd a = function
| 0 -> a
| b -> gcd b (a % b)
gcd 10 25
The compiler moves gcd to a private member, but nesting it within the assignment allows for tighter scoping. Function arguments, on the other hand, are more restricted. They don't create a new scope (that I'm aware of) and you can't define functions, for example, as part of the expression.
:= is a function (try (:=);; in FSI) which has a type : 'a ref -> 'a -> unit
So
b := // does not work
printfn "%A" a
4. + 8.
is being parsed as because of the infix call parsing rule:
(:=) b (printfn "%A" a)
4. + 8.
Which is invalid as par the (:=) function type.
Other example:
let c = 10 +
11
12
c would be 12 here
Looks like a discrepancy in the indentation-sensitive parser rather than anything specifically to do with those operators.
F# allows to use checked arithmetics by opening Checked module, which redefines standard operators to be checked operators, for example:
open Checked
let x = 1 + System.Int32.MaxValue // overflow
will result arithmetic overflow exception.
But what if I want to use checked arithmetics in some small scope, like C# allows with keyword checked:
int x = 1 + int.MaxValue; // ok
int y = checked { 1 + int.MaxValue }; // overflow
How can I control the scope of operators redefinition by opening Checked module or make it smaller as possible?
You can always define a separate operator, or use shadowing, or use parens to create an inner scope for temporary shadowing:
let f() =
// define a separate operator
let (+.) x y = Checked.(+) x y
try
let x = 1 +. System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
// shadow (+)
let (+) x y = Checked.(+) x y
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
// shadow it back again
let (+) x y = Operators.(+) x y
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
// use parens to create a scope
(
// shadow inside
let (+) x y = Checked.(+) x y
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
)
// shadowing scope expires
try
let x = 1 + System.Int32.MaxValue
printfn "ran ok"
with e ->
printfn "exception"
f()
// output:
// exception
// ran ok
// exception
// ran ok
// exception
// ran ok
Finally, see also the --checked+ compiler option:
http://msdn.microsoft.com/en-us/library/dd233171(VS.100).aspx
Here is a complicated (but maybe interesting) alternative. If you're writing something serious then you should probably use one of the Brians suggestions, but just out of curiosity, I was wondering if it was possible to write F# computation expression to do this. You can declare a type that represents int which should be used only with checked operations:
type CheckedInt = Ch of int with
static member (+) (Ch a, Ch b) = Checked.(+) a b
static member (*) (Ch a, Ch b) = Checked.(*) a b
static member (+) (Ch a, b) = Checked.(+) a b
static member (*) (Ch a, b) = Checked.(*) a b
Then you can define a computation expression builder (this isn't really a monad at all, because the types of operations are completely non-standard):
type CheckedBuilder() =
member x.Bind(v, f) = f (Ch v)
member x.Return(Ch v) = v
let checked = new CheckedBuilder()
When you call 'bind' it will automatically wrap the given integer value into an integer that should be used with checked operations, so the rest of the code will use checked + and * operators declared as members. You end up with something like this:
checked { let! a = 10000
let! b = a * 10000
let! c = b * 21
let! d = c + 47483648 // !
return d }
This throws an exception because it overflows on the marked line. If you change the number, it will return an int value (because the Return member unwraps the numeric value from the Checked type). This is a bit crazy technique :-) but I thought it may be interesting!
(Note checked is a keyword reserved for future use, so you may prefer choosing another name)