• # Plus verbeux que le C++

    Posté par (site web personnel, Mastodon) . En réponse au journal Sortie de GHC 8.0.2 et une petite histoire de typage statique. Évalué à 9.

    J'aime bien ces dépêches-là, ça m'oblige à réfléchir comment je ferai ça dans mon langage préféré, qui est... L'Ada :)
    J'ai donc tenté de faire les deux exemples.
    Attention, il y a peut-être mieux :

    with Ada.Text_Io; use Ada.Text_Io;
    procedure Variant is
     type Formes is (CARRE, RECTANGLE);
     type Forme(De_Type : Formes) is 
     record
     case De_Type is
     when CARRE =>
     Cote : Positive;
     when RECTANGLE =>
     Longueur : Positive;
     Largeur : Positive;
     end case;
     end record;
     function Surface(La_Forme : Forme) return Positive is
     begin
     case La_Forme.De_Type is
     when CARRE =>
     return La_Forme.Cote ** 2;
     when RECTANGLE =>
     return La_Forme.Longueur * La_Forme.Largeur;
     end case;
     end Surface;
     Mon_Carre : Forme := Forme'(De_Type => CARRE, Cote => 2);
     Mon_Rectangle : Forme := Forme'(De_Type => Rectangle, Longueur => 5, Largeur => 2);
    begin
     Put_Line("Surface " & Positive'Image(Surface(Mon_Carre)));
     Put_Line("Surface " & Positive'Image(Surface(Mon_Rectangle)));
    end Variant;

    L'avantage ici est que, comme en Haskell, il est impossible dans un CASE d'oublier une alternative, le compilateur ne voudra jamais.
    De fait, l'ajout d'un élément à l'énumération va forcer le développeur à compléter son record et aussi à compléter la fonction Surface.
    J'ai laissé de côté la notion de mutabilité des variants mais pour ceux que ça intéresse, c'est :)

    Pour le deuxième exemple, c'est plus facile, la programmation multi-processeurs fait partie de la norme et la version 2012 du langage a introduit l'annexe Multiprocessors (ça, c'est )

    with System.Multiprocessors; use System.Multiprocessors;
    with Ada.Text_Io; use Ada.Text_Io;
    procedure MT is
     type CPU_CONFS is (TOUS_LES_CPUS, LA_MOITIE_SEULEMENT, AUTRE_CHOSE);
     subtype NB_CPU is CPU range 1 .. Number_Of_CPUs;
     procedure SetGlobalThreadCount (Config : CPU_CONFS) is -- TOUS_LES_CPUS est comme CPU'Last
     begin
     -- Quelque chose ici avec des Task et autres joyeusetés
     -- en fontion de la conf
     case Config is
     when TOUS_LES_CPUS =>
     Put_Line ("Zou, à fond " & CPU'Image(Number_Of_CPUs));
     when LA_MOITIE_SEULEMENT =>
     Put_Line ("Mollo " & CPU'Image(Number_Of_CPUs / 2));
     when AUTRE_CHOSE =>
     Put_Line("Smart");
     end case;
     end SetGlobalThreadCount;
     procedure SetGlobalThreadCount (combien : NB_CPU) is
     begin
     -- Un autre truc en fonction du nombre de CPU
     Put_Line("nb CPU : " & NB_CPU'Image(combien));
     end SetGlobalThreadCount;
    begin
     SetGlobalThreadCount(LA_MOITIE_SEULEMENT);
     SetGlobalThreadCount(12);
    end MT;

    Number_Of_CPUs étant une fonction dont la valeur n'est pas connue à la compilation, le compilateur ne détecte pas que 12 CPUs, c'est trop... Ça donne une jolie exception CONTRAINT_ERROR qu'il reste à gérer.

    Voilà donc ma petite contribution et merci pour le petit exercice et cette petite présentation bien sympa d'exemples de typage statique en Haskell.