F# basics

Some basics of F#

#light

This directive (hash light) is used to simplify the F# syntax. Meaning the syntax is a little less verbose and removes aspects of the OCaml compatibility.

Immutable by default

By default “variables” are really just “values” as they are immutable by default so

let n = 100

initializes n to the value 100 and you cannot now alter n.

However we can mark a value as mutable and thus is can be altered, for example

let mutable n = 100
n <- n + 1

n is set to be a mutable type and n <- n + 1 is the assignment line of code, assigning n the new value of n + 1.

Assignment operator

As mentioned above, F# values are immutable, by marking them as mutable we can assign values to them. The assignment operator is not = but is <-, for example [code language="fsharp"] let mutable n = 10 // initializes n the value 10 n <- 100 // assignment of the value 100 [/code] ignore

Some functions return values which we might not actually wish to use. For example the following uses List.map to simply output the items in the array urls

let urls = ["http://www.bbc.co.uk";
             "http://www.google.co.uk";
             "http://www.amazon.co.uk"]

let f x = printfn "%s" x
List.map f urls

But the compiler will show a warning This expression should have type ‘unit’, but has type ‘unit list’. Use ‘ignore’ to discard the result of the expression, or ‘let’ to bind the result to a name for the line List.map f urls. To fix this either change this line to

let o = List.map f urls

or pipe the result to ignore as per

List.map f urls |> ignore

We can also use the following syntax

ignore(List.map f urls)

Semi-colon and commas in lists and arrays

To declare a list value in F# we use a semi-colon to denote each value of a list for example

let evens = [2;4;6;8;10;12]

This will create a val evens : int list = [2; 4; 6; 8; 10; 12]

Alternatively using a comma as per

let evens = [2,4,6,8,10,12]

This will create a val evens : (int * int * int * int) list = [(2, 4, 6, 8)]. The difference here is that with the comma we’re creating a tuple containing integers, not a list of integers.

Collection Types

List

A list is declared as

let list = [2;4;6;8;10]

Lists are ordered, immutable data of the same type.

Array

An array is declared as

let array = [|2;4;6;8;10|]

Array’s are fixed-size, zero based values of the same type.

Sequence

A sequence is declared as

let s = seq { 0 .. 10 .. 100 }

A sequence is a series of values of the same type.

Lambda expressions and anonymous functions

Anonymous functions are declared as follows

fun parameter-list -> expression

For example we might use an anonymous function in a List.map as follows

let urls = ["http://www.bbc.co.uk";
             "http://www.google.co.uk";
             "http://www.amazon.co.uk"]

List.map (fun x -> printfn "%s" x) urls

Comments

Single line comments are denoted in the same way as C# i.e.

// This is a comment

Multi-line comments are denoted using (*..*), i.e.

(*
This is a comment block
*)

Loops

The F# equivalent of a foreach

let a = [0 .. 6]
for i in a do
   printfn "%d" i

The for loop

for i = 1 to 10 do
   printfn "%d" i

for j = 10 downto 1 do
   printfn "%d" j

The while loop

let aa = [|0 .. 6|]
let mutable i = 0
  while i < (Array.length aa) do
     printfn "%d" (Array.get aa i)
     i <- i + 1

The unit type

Functions which take no arguments and/or return no values are said to take and return the type unit. This can be seen as being analogous to void in C#.

The double backtick “ in identifiers

As per Identifiers and Keywords. We can use the double backtick “ to enclose identifier that might be a language keyword, for example

let ``private`` = 1

is valid even though private is a keyword. We can also have spaces in identifiers such as

let ``add two numbers`` () =
   // function definition