Ocaml: module Format et autres

Anne ocaml

Au sujet de Format.fprintf et Scanf.format_from_string

Indentation en ocaml avec Format

Je me bat souvent pour obtenir une indentation correcte lors de l’affichage de mes structures de donnée en ocaml, alors voilà un petit exemple pour mémoire.

let rec pp_tree fmt t = match t with
  | D str -> Format.fprintf fmt "@,'%s'" str
  | E (name, t) -> Format.fprintf fmt "@,@[<v2>'%s' {%a@]@,}"
                     name pp_list_tree t
and pp_list_tree fmt l = match l with [] -> ()
  | x::tl -> Format.fprintf fmt "%a%a" pp_tree x pp_list_tree tl

On peut modifier la chaîne de fermeture de "@]@,}" en "@,}@]" si on préfère aligner ‘}’ sur les fils plutôt que sur les pères.

La fonction format_of_string

Je n’ai pas tout de suite compris comment utiliser la fonction Scanf.format_from_string comme on peut le voir dans ma question sur Stackoverflow.

La chaîne qui décrit le format n’est pas de type string comme les autres chaînes. Elle a un type complexe qui permet au compilateur de vérifier que les types des arguments sont corrects. Quand on utilise une chaîne en dehors du contexte des fonction d’affichage, pour initialiser une variable par exemple, elle est par défaut interprétée comme de type string. Si on souhaite forcer l’interprétation de type format, on peut utiliser la fonction format_of_string, mais ça n’a un sens que s’il s’agit d’une chaîne constant qui permet de déterminer le bon type.

Lorsqu’on a une chaîne que l’on veut interpréter comme un format, on ne peut le faire que si on connaît le type des arguments attendus. On peut alors utiliser la fonction Scanf.format_from_string. Par exemple, si on sait que la chaîne str représente un format sans argument, on peut faire :

let msg = Scanf.format_from_string str "" in
    Format.fprintf fmt ("  - "^^msg^^"@.")

Si à l’exécution, la chaîne str n’a pas le bon type, une exception est levée :

Exception:
Scanf.Scan_failure "format read 'abc%d' does not match specification ''".

Voir aussi :