web-dev-qa-db-fra.com

Imprimer une liste dans OCaml

Je veux faire quelque chose d'aussi simple que cela:

Imprimez une liste.

let a = [1;2;3;4;5]

Comment imprimer cette liste sur la sortie standard?

33
Gitmo

Vous pouvez le faire avec une récursivité simple:

let rec print_list = function 
[] -> ()
| e::l -> print_int e ; print_string " " ; print_list l

Le titre de la liste est imprimé, puis vous effectuez un appel récursif en fin de liste.

35
Ackar

Vous devez vous familiariser avec les fonctions List.iter et List.map. Ils sont essentiels pour la programmation dans OCaml. Si vous vous familiarisez également avec le module Printf, vous pouvez alors écrire:

open Printf
let a = [1;2;3;4;5]
let () = List.iter (printf "%d ") a

J'ouvre Printf dans la plupart de mon code car j'utilise les fonctions qu'il contient si souvent. Sans cela, vous devrez écrire Printf.printf à la dernière ligne. De plus, si vous travaillez dans le toploop, n'oubliez pas de terminer les instructions ci-dessus avec des doubles points-virgules.

54
Ashish Agarwal
print_string (String.concat " " (List.map string_of_int list))
27
Fabrice Le Fessant

Si la question est de trouver le moyen le plus rapide de l'implémenter, par exemple lors du débogage, alors nous pourrions dire que:

  • les bibliothèques standard étendues (par exemple, les batteries) ont généralement des fonctions supplémentaires:

    List.print
      ~first:"[" ~sep:";" ~last:"]" (fun c x -> Printf.fprintf c "%d" x) stdout a
    
  • ce petit extension de syntaxe que j'ai écrit il y a quelque temps vous permet d'écrire:

    <:print<[$!i <- a${$d:i$}{;}]>>
    
  • la génération automatique n'est pas immédiatement disponible (en raison du manque d'informations sur le type d'exécution dans la représentation des données OCaml) mais peut être obtenue en utilisant soit la génération de code à partir des types, soit des types d'exécution.
7
Tiphaine Turpin

Je réponds très tard, mais voici une autre façon:

let print_list f lst =
  let rec print_elements = function
    | [] -> ()
    | h::t -> f h; print_string ";"; print_elements t
  in
  print_string "[";
  print_elements lst;
  print_string "]";;

Pour imprimer une liste int, nous pourrions écrire:

print_list print_int [3;6;78;5;2;34;7];;

Cependant, si nous devions faire cela beaucoup, cela gagnerait du temps pour spécialiser la fonction en utilisant une application partielle:

let print_int_list = print_list print_int;;

Que nous pouvons maintenant utiliser comme ceci:

print_int_list [3;6;78;5;2;34;7];;

Et si nous voulions faire quelque chose d'assez complexe, comme imprimer une liste de liste int? Avec cette fonction, c'est simple:

(* Option 1 *)
print_list (print_list print_int) [[3;6;78];[];[5];[2;34;7]];;

(* Option 2 *)
let print_int_list_list = print_list (print_list print_int);;
print_int_list_list [[3;6;78];[];[5];[2;34;7]];;

(* Option 3 *)
let print_int_list_list = print_list print_int_list;;
print_int_list_list [[3;6;78];[];[5];[2;34;7]];;

Impression d'une liste (int * chaîne) (c'est-à-dire une liste de paires d'entiers et de chaînes):

(* Option 1 *)
print_list (fun (a, b) -> print_string "("; print_int a; print_string ", "; print_string b; print_string ")") [(1, "one"); (2, "two"); (3, "three")];;

(* Option 2 *)
let print_pair f g (a, b) =
  print_string "(";
  f a;
  print_string ", ";
  g b;
  print_string ")";;
print_list (print_pair print_int print_string) [(1, "one"); (2, "two"); (3, "three")];;

(* Option 3 *)
let print_pair f g (a, b) =
  print_string "(";
  f a;
  print_string ", ";
  g b;
  print_string ")";;
let print_int_string_pair = print_pair print_int print_string;;
print_list print_int_string_pair [(1, "one"); (2, "two"); (3, "three")];;

(* Option 4 *)
let print_pair f g (a, b) =
  print_string "(";
  f a;
  print_string ", ";
  g b;
  print_string ")";;
let print_int_string_pair = print_pair print_int print_string;;
let print_int_string_pair_list = print_list print_int_string_pair;;
print_int_string_pair_list [(1, "one"); (2, "two"); (3, "three")];;
6
Bertie Wheen

Je le ferais de la manière suivante:

let a = [1;2;3;4;5];;
List.iter print_int a;;
3
akshaynagpal

Juste une solution avec% a:

open Printf
let print_l outx l = 
     List.map string_of_int  l
  |> String.concat ";"
  |> fprintf outx "%s"

Test:

# printf "[%a]" print_l [1;2;3] ;;
[1;2;3]- : unit = ()
# printf "[%a]" print_l [];;
[]- : unit = ()
2
V. Michel

En fait, vous pouvez découpler l'impression d'une liste et la transformer en chaîne. Le principal avantage pour cela est que vous pouvez utiliser cette méthode pour afficher les listes dans les journaux, les exporter vers des CSV ...

J'utilise souvent un module listHelper, avec les éléments suivants:

(** Generic method to print the elements of a list *)
let string_of_list input_list string_of_element sep =
  let add a b = a^sep^(string_of_element b) in
  match input_list with
  | [] -> ""
  | h::t -> List.fold_left add (string_of_element h) t

Donc, si je voulais sortir une liste de flottants dans un fichier csv, je pourrais simplement utiliser ce qui suit:

let float_list_to_csv_row input_list = string_of_list input_list string_of_float "," 
2
RUser4512
let print_list l =
  let rec aux acc =
    match acc with
     | [] -> ()
     | x :: tl ->
       Printf.fprintf stdout "%i"; aux tl
   in aux l

Ou

let sprintf_list l =
  let acc = ref "{" in
  List.iteri (fun i x ->
    acc := !acc ^
      if i <> 0
      then Printf.sprintf "; %i" x
      else Printf.sprintf "%i" x
  ) l;
  !acc ^ "}"

let print_list l =
  let output = sprintf_list l in
  Printf.fprintf stdout "%s\n" output
1
Quyen