Dès qu’un programme prend un peu d’ampleur, on a rapidement envie d’unifier les fonctions servant à donner des messages, ne serait ce que pour y ajouter un préfixe facilement identifiable.
Affichage avec continuation
Une méthode fréquente est d’utiliser les fonction d’affichage avec continuation :
let info1 msg
let pp _fmt
let txt = Format.flush_str_formatter () in
Format.printf "@[<hov4>[my_prog] %s@]@." txt
in Format.kfprintf pp Format.str_formatter msg
ou encore plus simple :
let info2 msg
let pp txt = Format.printf "@[<hov4>[my_prog] %s@]@." txt
in Format.ksprintf pp msf
Ces deux méthodes fonctionnent, mais elles ont un défaut, c’est que comme on passe par une chaîne de caractères intermédiaire, on perd une partie du formatage, comme l’indentation par exemple.
Une amélioration est de faire :
let info3 msg
let fmt = Format.std_formatter in (* ou Format.err_formatter *)
Format.fprintf fmt "@[<hov4>[my_prog] ";
let pp fmt = Format.fprintf fmt "@]@."
in Format.kfprintf pp fmt msg
Ainsi, la boite est bien ouverte avant l’affichage du message, et tout se passe bien.
Erreurs et Warning
On peut ensuite écrire par exemple :
let warning fmt = info3 ("Warning: "^^fmt)
Par contre, pour une erreur, je ne vois pas comment faire pour réutiliser
la fonction info
.
Il faut donc utiliser le même principe :
let error n msg
let fmt = Format.err_formatter in
Format.fprintf fmt "@[<hov4>[my_prog] ";
let pp fmt = Format.printf "@]@." ; exit n
in Format.kfprintf pp fmt msg
Debug
Pour faire un affichage conditionnel, pour déboguer par exemple,
on utilise la fonction ifprintf
qui consomme les arguments
sans rien faire :
let debug_level = 2
let debug n fmt
if n <= debug_level then info fmt
else Format.ifprintf Format.str_formatter fmt
Failwith
Une autre fonction bien pratique est :
let failwithf fmt = Printf.ksprintf failwith fmt
Elle permet d'écrire par exemple :
failwithf "%s:%d: erreur !" fichier ligne
Curiosités
Dans la donc du module Printf
, on trouve deux formats étranges
dont je n’ai pas encore compris l’utilité :
Format.printf "format string substitution: %( %s%s %)@."
"@[nom: %s @\nprenom: %s@]" "x" "y";
Format.printf
"convert a format string argument to its type digest: %{ %s%s %}@."
"nom: %s - prenom: %s";
Ça donne :
format string substitution: nom: x
prenom: y
convert a format string argument to its type digest: %s%s
A la limite, j’imagine bien que la première peut servir à faire de l’internationalisation, mais la seconde ???
Voir aussi :
- Afficher un pourcentage dans une page HTML
- VNC : Virtual Network Computing
- Git : déménagement d'un dépôt
- Quelques liens au sujet de l'analyse statique
- Ocaml: mon principal langage de développement
- Disque dur externe
- Les profiles dans Firefox
- Cryptographie et mail sous Android
- Quelques liens au sujet du C
- Git rebase : pour diviser un commit