Recherche…


Syntaxe

  • val (|>) : 'a -> ('a -> 'b) -> 'b
  • val (@@) : ('a -> 'b) -> 'a -> 'b

Algorithmes génériques

Les fonctions d'ordre supérieur peuvent être utilisées pour implémenter des algorithmes génériques, en renonçant à fournir les détails finaux à l'utilisateur. Par exemple, List.sort attend une fonction de comparaison permettant d'implémenter différentes méthodes de tri. Ici, nous implémentons un tri des chaînes sans tenir compte de la casse:

let string_case_insensitive_sort lst =
  let case_insensitive_compare a b =
    String.compare (String.lowercase a) (String.lowercase b)
  in
  List.sort case_insensitive_compare lst

Il y a une liste riche de fonctions d'ordre supérieur dans la bibliothèque standard, en particulier dans le module List , voir List.fold_left et List.sort par exemple. Des exemples plus avancés peuvent être trouvés dans des bibliothèques tierces. Un bon exemple est le recuit simulé implémenté dans ocaml-gsl . Le recuit simulé est une procédure d'optimisation générique paramétrée par une fonction permettant d'explorer l'ensemble des états du problème et une fonction d'erreur (appelée ici fonction énergétique).

Les utilisateurs familiers avec C ++ peuvent comparer cela au modèle de stratégie .

Éliminer les ressources du système même lorsqu'une exception est déclenchée

Les fonctions d'ordre supérieur peuvent être utilisées pour garantir que les ressources du système sont éliminées, même lorsqu'un traitement déclenche une exception. Le modèle utilisé par with_output_file permet une séparation nette des problèmes: les fonctions with_output_file ordre with_output_file prennent en charge la gestion des ressources système liées à la manipulation de fichiers, tandis que le traitement f ne consomme que le canal de sortie.

let with_output_file path f =
  let c = open_out path in
  try
    let answer = f c in
    (close_out c; answer)
  with exn -> (close_out c; raise exn)

Utilisons cette fonction d'ordre supérieur pour implémenter une fonction écrivant une chaîne dans un fichier:

let save_string path s =
  (with_output_file path) (fun c -> output_string c s)

En utilisant des fonctions plus avancées que fun c -> output_string cs il est possible de sauvegarder des valeurs plus complexes. Voir par exemple le module Marshal dans la bibliothèque standard ou la bibliothèque Yojson de Martin Jambon.

Opérateurs de composition

Deux fonctions utiles d'ordre supérieur sont les opérateurs d' application binaire ( @@ ) et d' inversion d'application ou "pipe" ( |> ). Bien que, depuis la version 4.01, ils soient disponibles en tant que primitives, il pourrait être intéressant de les définir ici:

let (|>) x f = f x
let (@@) f x = f x

Considérons le problème de l'incrémentation du carré de 3. Une façon d'exprimer ce calcul est la suivante:

(* 1 -- Using parentheses *)
succ (square 3)
(* - : int = 10 *)

(* where `square` is defined as: *)
let square x = x * x

Notez que nous ne pouvions pas simplement faire un succ square 3 car (en raison de l’ associativité gauche ), cela se réduirait au (succ square) 3 sans signification (succ square) 3 . En utilisant l'application ( @@ ), nous pouvons exprimer cela sans les parenthèses:

(* 2 -- Using the application operator *)
succ @@ square 3
(* - : int = 10 *)

Remarquez comment la dernière opération à effectuer (à savoir succ ) se produit en premier dans l'expression? L'opérateur d' inversion d'application ( |> ) nous permet de bien inverser ceci:

(* 3 -- Using the reverse-application operator *)
3 |> square |> succ
(* - : int = 10 *)

Le nombre 3 est maintenant "canalisé" par square puis succ , au lieu d'être appliqué au square pour donner un résultat auquel succ est appliqué.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow