• [^] # Re: Méconnaissance

    Posté par . En réponse au journal Compilateur et Monad Reader. Évalué à 5. Dernière modification le 22 novembre 2015 à 16:31.

    Je ne répond pas pour ajouter quelque chose au commentaire de Dinosaure, mais pour interroger ceux qui l'ont moinsé ? Why ?

    Pour rappel, Dinosaure est l'organisateur des rencontres OCaml User In Paris et donc un développeur OCaml expérimenté.

    Sa réponse était certes lapidaire, mais on ne peut plus juste.
    Ainsi, après avoir définit son opérateur infixe, le code d'aluminium95 :

    (* Et on peut les composer sans passer explicitement le contexte *)
    let push_var_on_stack s = 
     bind get_var_addr (* chaine la fonction get_var_addr *)
     (fun addr -> 
     pushq addr);;

    devient

    let ( >>= ) = bind;;
    let push_var_on_stack s = get_var_addr s >>= pushq;;

    comme proposé par le tout premier commentaire, c'est plus compliqué que la notation do ?

    En programmation fonctionnelle, on manipule des fonctions et des opérateurs, et donc on les compose (comme en mathématique). On utilise la notation infixe pour les opérateurs de composition, comme le pipe du shell qui en OCaml se définit usuellement :

    let ( |> ) f g = g f;;
    (* exemple *)
    # [1; 2; 3] |> List.map (( + ) 2);;
    - : int list = [3; 4; 5]

    Là où son code Haskell final était :

    -- Et on peut les composer sans passer explicitement le contexte
    push_var_on_stack s = do 
     addr <- get_var_addr s 
     pushq addr

    Autrement dit on applique la sortie de get_var_addr à pushq, ce qu'exprime justement l'opérateur bind, ou sa version infixe >>=.

    Je maintiens que la notation infixe est bien plus compréhensible et lisible quand on raisonne d'un point de vue fonctionnel.
    D'une ce n'est pas plus long à écrire, et un code est bien plus souvent lu qu'il n'est écrit.
    De deux, aluminium écrit trop :

    (* écrire *)
    let _ = fun addr -> pushq addr;;
    (*ou écrire *)
    pushq;;
    (* c'est du pareil au même, son code de base étant donc *)
    let push_var_on_stack s = 
     bind (get_var_addr s) pushq;;
    (* et en notation infixe *)
    let push_var_on_stack s = (get_var_addr s) >>= pushq;;

    Un traitement séquentiel n'est rien d'autre qu'une composition de fonctions et d'opérateurs, pourquoi nommé localement le résultat d'une sortie pour le réaffecter immédiatement dans l'entrée de l'opérateur suivant ? Autant dire : je compose les opérateurs.

    @ aluminium95 : comme tu es en première année de l'ENS cachan, et donc en région parisienne, un petit tour au OUPS pourrait t'intéresser. À voir avec Dinosaure si le niveau est accessible à un L1.

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