2012-02-03 4 views
28

Я хочу сделать что-то простое:Распечатайте список в OCaml

Распечатать список.

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

Как распечатать этот список до стандартного вывода?

+0

Что вы пытаетесь? Знаете ли вы о спецификации формата '% a' (для пользовательской печати)' Printf.printf'? –

+0

Я только начал изучать OCaml. Я пробовал спецификацию формата% d. На самом деле я не знал о ';' что позволяет указать более одного утверждения - как в ответе ackar. – Gitmo

ответ

28

Вы можете сделать это с помощью простой рекурсии:

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

Глава списка печатается, то рекурсивный вызов на хвосте списка.

+19

Я бы добавил, что переписывание 'List.iter' кажется позором. – Ashe

+3

Я согласен с этим. Но все же интересно понять, как работают списки. – Ackar

+0

, конечно, и я не согласен. – Ashe

47

Вам следует ознакомиться с функциями List.iter и List.map. Они необходимы для программирования в OCaml. Если вы освоитесь с модулем PRINTF, вы можете написать:

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

Я открываю Printf в большинстве своем коде, потому что я использую функции в ней так часто. Без этого вам придется написать Printf.printf в последней строке. Кроме того, если вы работаете в toploop, не забудьте закончить вышеуказанные утверждения двойными полуколонами.

+2

Если вы используете модуль List из Core (например, вы следуете за Real World Ocaml), вам нужно сделать следующее: 'List.iter ~ f: (printf"% d ") a' – esl

+0

Вам действительно нужно добавить '~ f: '? – Anders

23
print_string (String.concat " " (List.map string_of_int list)) 
6

Если речь идет о поиске quickiest способ осуществить это, например, при отладке, то можно сказать, что:

  • расширенные стандартные библиотеки (например, батареи), как правило, имеют некоторые дополнительные функции :

    List.print 
        ~first:"[" ~sep:";" ~last:"]" (fun c x -> Printf.fprintf c "%d" x) stdout a 
    
  • это крошечное syntax extension, что я написал некоторое время назад позволяет писать:

    <:print<[$!i <- a${$d:i$}{;}]>> 
    
  • Автоматическая генерация не доступна сразу (из-за отсутствия информации о времени выполнения в представлении данных OCaml), но может быть достигнута с использованием либо генерации кода из типов, либо типов времени выполнения.
4

Я очень поздно ответ, но вот еще один способ:

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 "]";; 

Чтобы напечатать список Int, мы могли бы написать:

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

Однако, если мы будем делать это много, это сэкономит время для специализации функции с использованием частичного применения:

let print_int_list = print_list print_int;; 

Что теперь мы можем использовать так:

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

Что делать, если мы хотим сделать что-то очень сложное, как печать списка списка INT? С этой функцией это легко:

(* 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]];; 

Печать списка (int * string) (т.список пар целых чисел и строк):

(* 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")];; 
+0

Интересно, что единственный «недостаток» всегда есть дополнительный ';' в списке. Например: '[[4; 2;]; [2;];]' – liweijian

+0

Я добавил дополнительную ветвь в функцию 'print_elements', и теперь это отлично :) – liweijian

0
let print_list l = 
    let rec aux acc = 
    match acc with 
    | [] ->() 
    | x :: tl -> 
     Printf.fprintf stdout "%i"; aux tl 
    in aux l 

Или

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

Я хотел бы сделать это следующим образом:

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

Почему бы не' List.iter print_int a ;; '? – Mars

+1

должен быть 'List.iter a print_int ;;' – nnyby

+0

@nnyby https://ocaml.org/learn/tutorials/camlp4_3.10/foreach_tutorial.html говорит, что это должно быть 'List.iter print_int a ;;' – akshaynagpal

0

Просто решение с% а :

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

Тест:

# printf "[%a]" print_l [1;2;3] ;; 
[1;2;3]- : unit =() 
# printf "[%a]" print_l [];; 
[]- : unit =() 
Смежные вопросы