• [^] # Re: Raisons d'essayer Rust

    Posté par . En réponse au journal Retour d'expérience sur les langages de programmation. Évalué à 2.

    Outre le cas de gestion des erreurs en renvoyant un type somme, il me semble étrange qu'un langage moderne ne dispose pas de types sommes. Cela ne rend pas le système de type plus complexe, ni plus dur à implémenter.

    Les adeptes des types algébriques ont un slogan qui dit « types as propositions », qui est à mon sens un abus de langage. Un type c'est un concept, mais un concept il faut d'abord le définir et pour cela utiliser une... proposition. Le slogan confond, d'une certaine façon, le défini avec sa définition. Mais, ceci étant, l'absence de type somme fait que l'on ne peut pas écrire de définition disjonctive (type somme) mais seulement des définitions conjonctives (type produit, comme les couples). La disjonction (ou somme) c'est le dual de la conjonction (ou produit) : son absence est difficilement justifiable. Que dirai-t-on d'un langage qui ne fournirait pas l'opérateur xor sur un type booléen mais seulement le and ? Il amputerait grandement les capacités d'expression du programmeur.

    En revanche, il est vrai que la gestion d'un tel type somme pour la gestion des erreurs peut rendre le code plus verbeux sans constructions adéquates dans le langage. Cela oblige à travailler dans une monade et, jusqu'à l'an dernier, c'était assez lourd syntaxiquement en OCaml. Contrairement à Haskell et sa do notation, mais je ne sais pas comment s'y prend Rust.

    D'ailleurs, pour reprendre une partie de ton journal, c'était moins lourd de travailler avec des exceptions que des type option ou result.

    let test i j =
     let i = int_of_string i in
     let j = int_of_strinf j in
     i + j
    test "12" "5";;
    - : int = 17
    test "coin" "5";;
    Exception: Failure "int_of_string".

    Si on prend une fonction de conversion qui renvoie une option au lieu d'une exception cela devient beaucoup plus lourd :

    let ios s = try Some (int_of_string s) with _ -> None
    let test i j =
     match ios i with
     | None -> None
     | Some i -> match ios j with
     | None -> None
     | Some j -> Some (i + j)
    test "12" "5";;
    - : int option = Some 17
    test "coin" "5";;
    - : int option = None

    Ou alors, pour être plus générique dans le pattern de code, on utilisera la monade d'option (ce qui complique grandement la charge cognitive pour le programmeur).

    let (>>=) o f = match o with None -> None | Some x -> f x
    let return x = Some x
    let test i j =
     ios i >>= fun i ->
     ios j >>= fun j ->
     return (i + j)
    test "12" "5";;
    - : int option = Some 17
    test "coin" "5";;
    - : int option = None

    Heureusement, depuis un an, on peut écrire un code moins abscons et plus proche de la version avec exception, mais c'est très récent.

    let (let*) = (>>=)
    let test i j =
     let* i = ios i in
     let* j = ios j in
     return (i + j)
    test "12" "5";;
    - : int option = Some 17
    test "coin" "5";;
    - : int option = None

    N'ayant jamais utiliser Rust, on doit s'y prendre comment pour travailler dans une telle monade ?

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.