« Objective Caml » : différence entre les versions

Contenu supprimé Contenu ajouté
Yoric (discussion | contributions)
Yoric (discussion | contributions)
Ligne 288 :
</pre>
 
La première partie de l'extrait définit un filtre sur les flux (streams) nommé <precode>add_line_number</precode>. Ce filtre est conçu pour traiter les flux de lignes, et son rôle est d'ajouter au début de chaque ligne le numéro de cette ligne. Les symboles <precode>[:</precode>, <precode>:]</precode> et <precode>`</precode> sont utilisés pour examiner le contenu d'un flux ou construire de nouveaux flux. Ainsi, <precode>[: :]</precode> désigne le flux vide et <precode>[: `line; rest :]</precode> désigne n'importe quel flux (d'entrée) non vide, dans lequel on choisit d'appeler <pre>line</pre> le premier élément et <pre>rest</pre> la suite. De même, <precode>[: `((string_of_int i)^": "^line); ...</precode> désigne le flux (de sortie) dans lequel le premier élément s'obtient en convertissant l'entier i en chaîne de caractère, chaîne à laquelle on concatène le symbole <precode>": "</precode> suivi de <precode>line</precode> (qui représente, rappelons-le, le premier élément du flux d'entrée). Enfin, <precodee>... ; add_line_number (i+1) rest :]</precode> désigne la suite du flux de sortie, qui s'obtient en continuant la boucle <precode>add_line_number</precode>, dans laquelle le nombre i est remplacé par i+1 et dans laquelle on s'intéresse à flux <precode>rest</precode> (qui représente toujours la suite du flux d'entrée).
 
La boucle <precode>add_line_number</precode> se lit donc
 
* tant que le flux d'entrée n'est pas épuisé, prendre le prochain élément (appelons-le 'line') et utilisons-le pour construire le prochain élément du flux de sortie -- cet élément aura pour valeur la représentation du nombre i (le numbre de lignes rencontrées depuis le début de la boucle), suivi de deux points, suivi de 'line'
* une fois le flux d'entrée épuisé, le flux de sortie est terminé.
 
La deuxième partie de l'extrait fait appel à des fonctions définies dans une bibliothèque :
 
* <code>with_input</code> ouvre un fichier en lecture, exécute une tâche sur ce fichier puis le referme, y compris en cas d'erreur
* <code>with_output</code> ouvre un fichier en écriture, exécute une tâche sur ce fichier puis le referme, y compris en cas d'erreur
* <code>output_lines</code> écrit le contenu d'un flux de lignes dans un fichier (ici, il s'agit du flux de sortie construit plus haut)
* <code>input_lines</code> lit un fichier comme une suite de lignes, sous la forme d'un flux (ici, il s'agit du flux d'entrée consulté plus haut).
 
Cet extrait se lit donc 'Ouvrons pour lecture le fichier "/tmp/in.txt" en nous assurant qu'il sera refermé à la fin de notre tâche et appelons son contenu input. Ouvrons pour écriture le fichier "/tmp/out.txt" en nous assurant qu'il sera refermé à la fin de notre tâche et appelons son contenu output. Lisons input ligne par ligne, appliquons le filtre add_line_number pour numéroter ces lignes, en partant du numéro 1, et écrivons le résultat de tout ceci dans output.'
Ligne 329 :
 
La complexité des deux programmes est comparable, même si l'on peut constater que, de nouveau, les bibliothèques de OCaml sont de plus haut niveau et
donc plus simples à composer sans commettre d'erreurs. En particulier, dans la version Java, de nombreuses erreurs peuvent se glisser, qui ne seraient pas détectées par le compilateur, par exemple oublier de fermer les flux, oublier d'avancer progressivement dans un flux, tester si la ligne est vide au lieu de déterminer si elle vaut <precode>null</precode>, utiliser <precode>equals</precode> au lieu de <precode>=!=</precode>etc.. À l'inverse, dans la version OCaml, le programmeur ne peut commettre aucune de ces erreurs.
 
Si nécessaire, OCaml fournit aussi les bibliothèques nécessaires pour gérer les fichiers à peu près de la même manière qu'en Java, ou pour traiter les expressions régulières.