Records

Points clés

Type produit, alternative au Tuple quand type imprécis sous forme de tuple

  • Exemple : float * float

    • Point dans un plan ?

    • Coordonnées géographiques ?

    • Parties réelle et imaginaire d'un nombre complexe ?

  • Record permet de lever le doute en nommant le type et ses éléments

type Point = { X: float; Y: float }
type Coordinate = { Latitude: float; Longitude: float }
type ComplexNumber = { Real: float; Imaginary: float }

Déclaration

  • Membres nommés en PascalCase, pas en camelCase

  • Membres séparés ; ou retours à la ligne

  • Saut de ligne après { qu'en cas de membre additionnels

type PostalAddress =type PostalAddress =
    { Address: string                {
      City: string                       Address: string
      Zip: string }         ┆             City: string
                            ┆             Zip: string
}
member x.ZipAndCity = $"{x.Zip} {x.City}"

🔗 https://docs.microsoft.com/en-us/dotnet/fsharp/style-guide/formatting

Instanciation

  • Même syntaxe qu'un objet anonyme C♯ sans new

    • Mais le record doit avoir été déclaré au-dessus !

  • Membres peuvent être renseignés dans n'importe quel ordre

    • Mais doivent tous être renseignés → pas de membres optionnels !

⚠️ Piège : cette syntaxe est similaire mais pas identique à celle de la déclaration → : pour définir le type du membre → = pour définir la valeur du membre

Les instances "longues" devraient être écrites sur plusieurs lignes :

Déconstruction

Même syntaxe pour déconstruire un Record que pour l'instancier :

💡 On peut ignorer certains champs → Rend explicite les champs utilisés 👍

⚠️ On ne peut pas déconstruire les membres additionnels tels que les propriétés !

Inférence

  • L'inférence de type ne marche pas quand on "dot" une string

  • ... mais elle marche avec un Record ?!

Pattern matching

Fonction inhabitantOf donnant le nom des habitants à une adresse :

Conflit de noms

En F♯, le typage est nominal et non pas structurel comme en TypeScript. → On peut écrire plusieurs fois le même Record avec les mêmes champs (cf. First et Last ci-dessous). → Il faut qualifier un champ avec le nom du Record pour lever l'ambiguïté sur le type.

Conseil : mieux vaut écrire des types distincts ou les séparer dans ≠ modules.

Modification

Record immuable mais facile de créer nouvelle instance ou copie modifiée

  • Expression de copy and update d'un Record

  • Syntaxe spéciale pour ne modifier que certains champs

  • Multi-lignes si expression longue

Différences C♯ / F♯ / JS

Limites 🛑

Lisibilité réduite quand plusieurs niveaux imbriqués

Record struct

Attribut [<Struct>] permet de passer d'un type référence à un type valeur :

⚖️ Pros/Cons d'une struct :

  • ✅ Performant car ne nécessite pas de garbage collection

  • ⚠️ Passée par valeur → pression sur la mémoire

👉 Adapté à un type "petit" en mémoire (~2-3 champs)

Last updated

Was this helpful?