Now I had intended to write a 1/2 decent blog post on F# operators, but then I had a think about this, and to be honest, I could not actually see too much merit in simply reiterating what was already freely available on MSDN where it lists ALL of the F# operators.
You can find a full list of all the F# operators and symbols on this MSDN page.
If you follow this link, the first thing you will realize is that F# has a lot of operators and symbols, far too many for me to include in a single blog post. With that in mind, I have taken my intention of creating a 1/2 decent blog post of operators, and decided to cut back the scope a bit to only include a discussion of the most common operators, so I guess you could say this blog will only be a 1/4 or 1/8 of a decent post, for which I humbly apologize.
Now before we start, I just wanted to say that I am only going to go through the most common operators, you will more than likely have to examine the MSDN link I included at the top of this post, when you really start to use F#, but for now I hope the ones I have chosen to concentrate on will be ok to get us started.
Oh one last thing, I am going to be pretty honest about this, so here goes, the brief description for each of the operators has been lifted directly from MSDN, it's one of those cases, when you are just meh “could not have said it better myself”, so didn’t and just borrowed um stole the stuff from MSDN.
Arithmetic Operators
The following table summarizes the binary arithmetic operators
+ Addition
Unchecked. Possible overflow condition when numbers are added together and the sum exceeds the maximum absolute value supported by the type.
- Subtraction
Unchecked. Possible underflow condition when unsigned types are subtracted, or when floating-point values are too small to be represented by the type.
* Multiplication
Unchecked. Possible overflow condition when numbers are multiplied and the product exceeds the maximum absolute value supported by the type.
/ Division
Division by zero causes a DivideByZeroException for integral types. For floating-point types, division by zero gives you the special floating-point values +Infinity or -Infinity. There is also a possible underflow condition when a floating-point number is too small to be represented by the type.
% Modulus
Returns the remainder of a division operation. The sign of the result is the same as the sign of the first operand.
** Exponentiation
Possible overflow condition when the result exceeds the maximum absolute value for the type. The exponentiation operator works only with floating-point types.
Demo
Here is a small demo of the Arithmetic operators listed above:
printfn "25 + 25 = %i" (25 + 25)
printfn "75 - 25 = %i" (75 - 25)
printfn "12 * 12 = %i" (12 * 12)
printfn "100 / 4 = %i" (100 / 4)
printfn "101 %% 10 = %i" (101 % 10)
printfn "2 ** 3 = %f" (2.0 ** 3.0)
And here is the result of running this:
Binary Operators
The following table shows the binary comparison operators that are available for integral and floating-point types. These operators return values of type bool
.
= Equals
This is not an assignment operator. It is used only for comparison. This is a generic operator.
> greater than
This is a generic operator.
< less than
This is a generic operator.
>= greater than or equal to
This is a generic operator.
<= greater than or equal to
This is a generic operator.
<> Not Equals
This is a generic operator.
Here is a small demo of the Binary operators listed above:
printfn "25 = 25 = %b" (25 = 25)
printfn "26 > 25 = %b" (26 > 25)
printfn "26 < 25 = %b" (26 < 25)
printfn "26 >= 25 = %b" (26 >= 25)
printfn "26 <= 25 = %b" (26 <= 25)
printfn "'a' <= 'b' = %b" ('a' <> 'b')
printfn "(1,'a') = (2,'a') = %b" ((1,'a') = (2,'a'))
printfn "(1,'a') = (1,'a') = %b" ((1,'a') = (1,'a'))
printfn "Some(1) = Some(2) = %b" (Some(1) = Some(2))
printfn "Some(2) = Some(2) = %b" (Some(2) = Some(2))
And here is the result of running this:
Boolean Operators
The following table summarizes the Boolean operators that are available in the F# language. The only type supported by these operators is the bool type.
not
Boolean negation
|| or
Boolean OR
&& and
Boolean AND
Here is a small demo of the Boolean operators listed above:
printfn "not true = %b" (not true)
printfn "true || false = %b" (true || false)
printfn "true && true = %b" (true && true)
printfn "true && false = %b" (true && false)
And here is the result of running this:
Bitwise Operators
The following table describes the bitwise operators that are supported for unboxed integral types in the F# language.
&&& and
Bitwise AND operator. Bits in the result have the value 1 if and only if the corresponding bits in both source operands are 1.
||| or
Bitwise OR operator. Bits in the result have the value 1 if either of the corresponding bits in the source operands are 1.
^^^ XOR
Bitwise exclusive OR operator. Bits in the result have the value 1 if and only if bits in the source operands have unequal values.
~~~ negation
Bitwise negation operator. This is a unary operator and produces a result in which all 0 bits in the source operand are converted to 1 bits and all 1 bits are converted to 0 bits.
<<< bit shift left
Bitwise left-shift operator. The result is the first operand with bits shifted left by the number of bits in the second operand. Bits shifted off the most significant position are not rotated into the least significant position. The least significant bits are padded with zeros. The type of the second argument is int32
.
>>> bit shift right
Bitwise right-shift operator. The result is the first operand with bits shifted right by the number of bits in the second operand. Bits shifted off the least significant position are not rotated into the most significant position. For unsigned types, the most significant bits are padded with zeros. For signed types, the most significant bits are padded with ones. The type of the second argument is int32
.
Here is a small demo of the Bit shift operators listed above:
printfn "2 &&& 4 (which is 0010 &&& 0100, should be 0) = %X" (2 &&& 4)
printfn "2 &&& 3 (which is 0010 &&& 0011, should be 2) = %X" (2 &&& 3)
printfn "2 ||| 4 (which is 0010 ||| 0100, should be 6) = %X" (2 ||| 4)
printfn "2 ||| 3 (which is 0010 ||| 0011, should be 3) = %X" (2 ||| 3)
printfn "2 ^^^ 4 (which is 0010 ^^^ 0100, should be 6) = %X" (2 ^^^ 4)
printfn "2 ^^^ 3 (which is 0010 ^^^ 0011, should be 1) = %X" (2 ^^^ 3)
printfn "~~~4 (which is not 0100, should be 1011 (B hex), or 11 decimal) = %X" (~~~4)
printfn "4 <<< 1 (which is 0100 <<< by 1 place left , should be 1000 (8 hex), or 8 decimal) = %X" (4 <<< 1)
printfn "4 >>> 1 (which is 0100 >>> by 1 place right , should be 0010 (2 hex), or 2 decimal) = %X" (4 >>> 1)
And here is the result of running this:
Operator Overloading
As I have already mentioned, there will be times when you do need to implement your own operator logic. In other .NET languages, this would be achieved by supplying your own operator overloads. It should come as no surprise that you need to do the same thing in F#. I did not want to get onto classes and OO just yet, but it kind of fits the current discussion so let's see how you might implement your own operators in a custom F# type.
Again, I have stolen this from MSDN. The following code illustrates a vector
class that has just two operators, one for unary minus and one for multiplication by a scalar. In the example, two overloads for scalar multiplication are needed because the operator must work regardless of the order in which the vector and scalar appear.
type Vector(x: float, y : float) =
member this.x = x
member this.y = y
static member (~-) (v : Vector) =
Vector(-1.0 * v.x, -1.0 * v.y)
static member (*) (v : Vector, a) =
Vector(a * v.x, a * v.y)
static member (*) (a, v: Vector) =
Vector(a * v.x, a * v.y)
override this.ToString() =
this.x.ToString() + " " + this.y.ToString()
For more information, you can see MSDN.