Bases

Comments

(* This is block
   comment *)


// And this is line comment


/// XML doc summary


/// <summary>
/// Full XML doc
/// </summary>

Variables

  • Values for the purists

  • Keyword: let to declare/name a value

  • No need for ; at the end of the declaration

  • Creates a Binding that is immutable by default

    • const in JS, readonly members in C♯

  • Mutable binding with let mutable

    • let en JS, var en C♯

    • ⚠️ The assignment operator is <-, not = used for equality

    • Use it sparingly, on a limited scope

Traps ⚠️

Don't confuse the mutability of a variable (the part on the left-side of the binding) with the mutability of an object (the part on the right-side of the binding).

  • let prevents the binding from being modified, i.e. assigning a new value to a variable.

  • let does not prevent an object from mutating...

  • ...with one exception: mutable structures (e.g. ArrayCollector) working by value: when you call a method that modifies a structure (e.g. Add or Close), you get a new copy. It's let mutable that allows you to keep a reference to this new value.

Dispose pattern

There are 2 ways to deal with an IDisposable object in a logical block and automatically call its Dispose method at the end of the block:

  • Replace let by use to bind the IDisposable object to a variable name

    • Ex #1: use stream = new MemoryStream()

    • Ex #2: use _ = logger.BeginScope(...)

  • Call the using function with the IDisposable object and an action on it

    • E.g. using (new MemoryStream()) (fun stream -> ...)

Pros/Cons:

  • use helps reduce the nesting/indentation level, but it's less explicit when the object is disposed.

  • using is more verbose, but also explicit.

Additional resources:

🔗 Resource Management: the use keyword 🔗 using function documentation

Names

  • Same constraints on variable naming as in C♯

  • ... except the apostrophe ' (tick)

    • allowed in the middle or at the end of the name, but not at the beginning!

    • at the end of the name → indicates a variant (code convention)

  • Between double backticks

    • allow any character, in particular whitespaces, except line breaks

Shadowing

  • Use to redefine a value with a name already used above → The previous value is no longer accessible in the current scope

  • Not allowed at module level but allowed in a sub-scope

  • Convenient but can be misleading → Not recommended, except in special cases

Type Annotation

  • Optional thanks to inference

  • The type is declared after the name name: type (like in TypeScript)

  • The value is mandatory, even with mutable which is a good constraint for the code 👍

Constant

  • What: Variable erased during compilation, every usage is replaced by the value

    • const C♯ - same idea than const enum in TypeScript

  • How: Value decorated with the Literal attribute ⚠️ Attributes are between [< >] → It's a frequent beginner error to use [ ] (like in C♯)

  • Recommended naming convention : PascalCase

Number

⚠️ No implicit conversion between number types

→ 💡 Use int, float, decimal helper functions to do this conversion

☝️ Note that this rule has been relaxed in some cases in F♯ 6.

String

Additional syntax:

String interpolation in F♯ 8

An interpolated string cannot contain braces ($"{xxx}") unless they are doubled ($"{{xxx}}"). Since F♯ 8, the $ character is doubled ($$$ )ortripled() or tripled () to indicate the number of braces from which interpolation starts, respectively {{ }} and {{{ }}}.

Conclusion: there are many many ways to write a string in F♯!

Encoding

String literals are encoded in Unicode:

We can work in ASCII using the B suffix, but in this case we get a byte array:

💡 Works also for character: 'a'B

Collections

  • Lists

  • Arrays

  • Sequences

Lists

A list is an immutable collection of elements of the same type. It's a different type than System.Collection.Generic.List<T> BCL type. It's implemented internally as a linked list.

Creation with [] • Items separated by ; or line breaks + indentation

⚠️ Trap: using , to separate items E.g. [ 1, 2 ] compiles but it is not a list of 2 items! It's a list of 1 item, a tuple of 2 elements! 📍

ML style type annotation: int list = List<int> → Idiomatic only for some FSharp.Core types: array, list, option 📍

List operators

:: Cons (for "construction"): add an item to the top of the list.. Range of numbers between min..max (included) or min..step..max@ Append 2 lists

⚠️ Space required before [] to create a list; otherwise: access by index

Arrays

Mutable fixed-size collections of elements of the same type.array 't = 't[]: BCL type

Creation with [||] • Items separated by ; or line breaks + indentation

⚠️ Trap: [] used for list creation and array type!

Sequences

Series of elements of the same type't seq = alias for System.Collections.Generic.IEnumerable<'t> BCL type

Creation with seq { }

⚠️ Lazy: possible multiple enumeration • hence not evaluated in FSI console

Collections functions

Each type has its own module containing dedicated functions.

Common functions:

F♯ collections

C♯ LINQ (IEnumerable<_>)

JS Array

map, collect

Select(), SelectMany()

map(), flatMap()

exists, forall

Any(predicate), All()

some(), every()

filter

Where()

filter()

find, tryFind

×

find()

fold, reduce

Aggregate([seed]])

reduce()

average, sum

Average(), Sum()

×

🔗 Full documentation on fsharp.github.io: ArrayListSeq

Last updated

Was this helpful?