(* ============================================== Operateurs definis par l'utilisateur en OCaml ============================================== *) (* ------------------------------------------------- 1. L'operateur pipe (|>) : "flot de donnees" ------------------------------------------------- *) (* Definition de l'operateur pipe *) let (|>) x f = f x (* Sans pipe : on lit de l'interieur vers l'exterieur *) let resultat1 = List.map (fun x -> x * x) (List.filter (fun x -> x mod 2 = 0) [1; 2; 3; 4; 5; 6]) (* Avec pipe : on lit de gauche a droite, comme un pipeline Unix *) let resultat2 = [1; 2; 3; 4; 5; 6] |> List.filter (fun x -> x mod 2 = 0) |> List.map (fun x -> x * x) let () = Printf.printf "sans pipe = [%s]\n" (String.concat "; " (List.map string_of_int resultat1)); Printf.printf "avec pipe = [%s]\n" (String.concat "; " (List.map string_of_int resultat2)) (* Il nous faut range *) let rec range n = if n <= 0 then [] else n :: range (n - 1) (* Exemple : somme des carres des impairs *) let somme_carres_impairs n = range n |> List.filter (fun x -> x mod 2 = 1) |> List.map (fun x -> x * x) |> List.fold_left (+) 0 let () = Printf.printf "somme_carres_impairs 5 = %d\n" (somme_carres_impairs 5) (* 1..5 impairs : 1, 3, 5 -> carres : 1, 9, 25 -> somme = 35 *) (* ------------------------------------------------- 2. Autres operateurs utiles ------------------------------------------------- *) (* Composition : f >> g = fun x -> g (f x) *) let (>>) f g x = g (f x) (* Application : x $ f = f x (inverse du pipe, plus faible priorite) *) let ($) f x = f x (* Pipe inverse : f <| x = f x (evite parentheses) *) let (<|) f x = f x (* Exemple : composition de fonctions *) let double = fun x -> 2 * x let carre = fun x -> x * x (* double_puis_carre : x -> (x*2)^2 *) let double_puis_carre = double >> carre let () = Printf.printf "double_puis_carre 5 = %d\n" (double_puis_carre 5) (* double 5 = 10, carre 10 = 100 *) (* ------------------------------------------------- 3. Operateurs numeriques personnalises ------------------------------------------------- *) (* Produit scalaire : v *** w *) let ( *** ) v w = List.fold_left2 (fun acc x y -> acc + x * y) 0 v w let () = Printf.printf "[1;2;3] *** [4;5;6] = %d\n" ([1; 2; 3] *** [4; 5; 6]) (* 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 *) (* Addition vectorielle *) let ( +++ ) v w = List.map2 (+) v w let () = Printf.printf "[1;2;3] +++ [4;5;6] = [%s]\n" (String.concat "; " (List.map string_of_int ([1; 2; 3] +++ [4; 5; 6]))) (* ------------------------------------------------- 4. Operateur pour travailler avec options ------------------------------------------------- *) (* Applicative sur option : f <$> x = Some f x si x est Some, None sinon *) let (<$>) f x = match x with | None -> None | Some x' -> Some (f x') (* (>>=) : monade option : x >>= f = f x si x est Some, None sinon *) let (>>=) x f = match x with | None -> None | Some x' -> f x' let () = Printf.printf "Some 5 <$> (fun x -> x * x) = %s\n" (match (fun x -> x * x) <$> Some 5 with Some n -> string_of_int n | None -> "None"); Printf.printf "None <$> (fun x -> x * x) = %s\n" (match (fun x -> x * x) <$> (None : int option) with Some n -> string_of_int n | None -> "None") (* ------------------------------------------------- 5. Priorite des operateurs ------------------------------------------------- *) (* En OCaml, la priorite est determinee par le premier caractere : - |>, <|, >> : priorite faible (autour de 0) - +, -, ++ : priorite 6 - *, /, ** : priorite 7 - $ : priorite 0 (la plus faible) *) (* Exemple : avec pipe pas besoin de parentheses *) let exemple_pipe n = n |> (+) 1 (* n + 1 *) |> ( * ) 2 (* (n + 1) * 2 *) |> succ (* (n + 1) * 2 + 1 *) let () = Printf.printf "exemple_pipe 5 = %d\n" (exemple_pipe 5) (* 5 -> 5+1=6 -> 6*2=12 -> 12+1=13 *) (* ------------------------------------------------- 6. Attention : masquage d'operateurs existants ------------------------------------------------- *) (* On peut surcharger (+) mais on masque l'original *) (* Decommenter pour tester : let (+) a b = a - b (* dangereux ! *) let () = Printf.printf "2 + 3 = %d (normalement 5...)\n" (2 + 3) *)