• [^] # Re: Merci !

    Posté par . En réponse au journal Portage de TapTempo en Ada. Évalué à 5. Dernière modification le 28 février 2018 à 18:41.

    D'ailleurs, je préfère la version verbeuse, je la trouve plus lisible ;)

    C'est parce que la pipeline est courte. Il faut voir cette notation pointée de Rust comme le pipe | du shell : reader.next() | unwrap_or | map_err | map. Sur de longues pipelines, c'est plus simple à écrire et il vaut mieux laisser le compilateur inliner le tout plutôt que de le faire à la main (comme dans sa version verbeuse, qui contient d'ailleurs une erreur : le cas None doit retourner Ok(false) de type Result<Bool, String>).

    En OCaml (j'étais bien obligé), on écrirait un code du genre :

    next reader |> Option.default (Ok "q") |> Result.map_both (fun s -> s <> "q") format_error

    Les patterns à base de map sont omniprésents dans le paradigme fonctionnel. Un type paramétrique à un paramètre (comme les options, les listes, les tableaux, les vecteurs...) est une fonction des types dans les types. Ainsi si j'ai une fonction qui transforme les objets du paramètre (disons des int en string), je peux la lifter pour opérer sur le type paramétrique (un peu comme une composition de fonction, si tu veux). Exemples :

    (* un int optionnel devient un string optionnel *)
    Option.map string_of_int (Some 1);;
    - : string option = Some u"1"
    (* une liste de ints devients une liste de strings *)
    List.map string_of_int [1; 2; 3];;
    - : string list = [u"1"; u"2"; u"3"]
    (* un tableau de ints devient un tableau de strings *)
    Array.map string_of_int [|1; 2; 3|];;
    - : string array = [|u"1"; u"2"; u"3"|]

    Le type Result est lui un type paramétrique à deux paramètres : on peut donc faire un map soit sur le type en paramètre de Ok, soit sur celui en paramètre de Err. Ce qui soit donne deux fonctions map (comme en Rust), soit une fonction map_both comme dans mon exemple en OCaml (ou bimap en Haskell) qui prend deux fonctions en paramètres (une pour chaque type).

    (* la double map pour le type result *)
    let bimap f g = function Ok x -> Ok (f x) | Error e -> Error (g e)
    (* le unwrap_or comme en Rust *)
    let unwrap_or d = function None -> d | Some x -> x
    (* la pipeline comme en Rust *)
    let pipeline x = 
     x
     |> unwrap_or (Ok "q")
     |> bimap (fun s -> s <> "q") ( Printf.sprintf "Houla y'a eu un truc: %s")
    (* exemples de sortie *)
    pipeline None;;
    - : (bool, string) result = Ok false
    pipeline (Some (Ok "f"));;
    - : (bool, string) result = Ok true
    pipeline (Some (Error "une erreur"));;
    - : (bool, string) result = Error u"Houla y'a eu un truc: une erreur"

    P.S : sinon sympa le journal, et comme depuis les derniers journaux sur la virgule flottante j'ai installé GNAT et GNAT Programming Studio je vais pouvoir regarder un code ADA idiomatique et jouer avec :-) (ravi de voir au passage qu'il y a des développeurs ADA qui comprennent l'encapsulation ;-).

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