F# Training
F# Training
F# Training
  • Presentation
  • Fundamentals
    • Introduction
    • Syntax
      • Bases
      • Functions
      • Rules
      • Exceptions
    • First concepts
    • šŸ”Quiz
  • Functions
    • Signature
    • Concepts
    • Syntax
    • Standard functions
    • Operators
    • Addendum
    • šŸ”Quiz
    • šŸ“œSummary
  • Types
    • Overview
    • Tuples
    • Records
    • Unions
    • Enums
    • Anonymous records
    • Value types
    • šŸ“œRecap
    • Addendum
  • Monadic types
    • Intro
    • Option type
    • Result type
    • Smart constructor
    • šŸš€Computation expression (CE)
    • šŸš€CE theoretical basements
    • šŸ“œRecap
  • Pattern matching
    • Patterns
    • Match expression
    • Active patterns
    • šŸš€Fold function
    • šŸ“œRecap
    • šŸ•¹ļøExercises
  • Collections
    • Overview
    • Types
    • Common functions
    • Dedicated functions
    • šŸ”Quiz
    • šŸ“œRecap
  • Asynchronous programming
    • Asynchronous workflow
    • Interop with .NET TPL
    • šŸ“œRecap
  • Module and Namespace
    • Overview
    • Namespace
    • Module
    • šŸ”Quiz
    • šŸ“œRecap
  • Object-oriented
    • Introduction
    • Members
    • Type extensions
    • Class, Struct
    • Interface
    • Object expression
    • Recommendations
Powered by GitBook
On this page
  • Declarations order
  • Indentation
  • Vertical line of indentation
  • Recommendations
  • Attributes
  • Addendum

Was this helpful?

Edit on GitHub
  1. Fundamentals
  2. Syntax

Rules

Declarations order

In a file, the declarations are ordered, from top to bottom. → Declaration comes before the usages.

In a .fsproj, the files are ordered too. → We can import only something previously declared.

Type inference works by proximity: the closest match will be used.

Balance:

  • Pros:

    • no cyclic dependencies

    • faster and more predictable compilation

    • code easier de reason about

  • Cons:

    • need more coding discipline

Example: we try to use the fn before its declaration:

let result = fn 2
//           ~~ šŸ’„ Error FS0039: The value or constructor 'fn' is not defined.

let fn i = i + 1

Indentation

  • In general, indentation is very important for code readability: → It creates visual structures that match the logical structure, the hierarchy.

  • The indentation is optional in C♯ because it's the combination of curly braces { } and semi-colons ; that defines the logical blocks. → These characters don't help the readability by themselves. It's the indentation that matters, then the curly braces can help to improve the block visual separation. → More importantly, a code not properly indented can be mis-interpreted, that can lead to bugs!

  • Indentation in F♯ is required:

    • It's the only way to define code blocks

    • Compiler ensures that the indentation is correct so the reader can really trust the indentation to understand the code structure.

šŸ‘‰ Conclusion: F♯ forces us to do what matters the most for the code readability šŸ‘

Vertical line of indentation

It's a concept a little more tricky, related to the way F♯ understands the indentation.

  • In general, a block starts in a new line, at a greater indentation level.

  • But sometimes a block can start in a middle of a line. In this case, this position defines the expected vertical indentation line.

let f =
   let x=1
   x+1
// ^ Vertical line here

let f = let x=1
        x+1
//      ^ Vertical line here!

Recommendations

  • In temporary fsx, speed to write code is usually more important than code readability. F♯ allows us some inconsistency and that's fine.

(*) Vanity alignment example:

// šŸ‘Œ OK
let myLongValueName =
    someExpression
    |> anotherExpression

// āš ļø To avoid
let myLongValueName = someExpression
                      |> anotherExpression  // šŸ‘ˆ Depend on the length of `myLongValueName`

Attributes

Attributes works like in C# to decorate a class, a method... with little character differences:

Lang
Separated attributes
Merged attributes

C#

[AttributeOne] [SecondAttribute]

[AttributeOne, SecondAttribute

F♯

[<AttributeOne>] [<SecondAttribute>]

[<AttributeOne>; <SecondAttribute>]

Addendum

PreviousFunctionsNextExceptions

Last updated 1 month ago

Was this helpful?

There are some exceptions to this rule, for instance with operators. šŸ”— , by Scott Wlaschin | F♯ for fun and profit.

ā˜ļø Indentation rules have been relaxed in .

In fsproj, proper and consistent formatting is important for maintainability. → Use consistently only spaces (no tabulations) → Use the same number of spaces for all indentation level, 4 spaces being idiomatic. The number spaces can vary only to fit the vertical indentation line (see details below). → Avoid naming-sensible indentation a.k.a Vanity Alignment (*) : • They can break compilation after a renaming. • Blocks too far at the right is less readable for a left-to-right language reader. → Use a code formatter like to ensure this consistency.

šŸ”—

šŸ”—

F♯ syntax: indentation and verbosity
F♯ 6
Fantomas
F♯ Cheatsheet
Troubleshooting F♯ - Why won't my code compile?