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:
letto declare/name a valueNo need for
;at the end of the declarationCreates a Binding that is immutable by default
≃
constin JS,readonlymembers in C♯
Mutable binding with
let mutable≃
leten JS,varen C♯⚠️ The assignment operator is
<-, not=used for equalityUse 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).
letprevents the binding from being modified, i.e. assigning a new value to a variable.letdoes 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.
AddorClose), you get a new copy. It'slet mutablethat 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
letbyuseto bind theIDisposableobject to a variable nameEx #1:
use stream = new MemoryStream()Ex #2:
use _ = logger.BeginScope(...)
Call the
usingfunction with theIDisposableobject and an action on itE.g.
using (new MemoryStream()) (fun stream -> ...)
Pros/Cons:
usehelps reduce the nesting/indentation level, but it's less explicit when the object is disposed.usingis 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
modulelevel but allowed in a sub-scopeConvenient 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
mutablewhich is a good constraint for the code 👍
Constant
What: Variable erased during compilation, every usage is replaced by the value
≃
constC♯ - same idea thanconst enumin TypeScript
How: Value decorated with the
Literalattribute ⚠️ 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 ($$$ ) 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: Array • List • Seq
Last updated
Was this helpful?