cscisgqr
cscisgqr

Reputation: 29

Print elements in list in OCaml

I want to write a tail recursive function to print elements in a string list in separate lines like this:

  # printlist ["a";"b";"c"];;
   a
   b
   c
   - : unit = ()
   # printlist ["hello";"thanks"];;
   hello
   thanks
   - : unit = ()

I was able to get it to work using print_endline with no problem:

let rec printlist strlist =
  match strlist with 
  | [] ->  print_endline "" 
  | hd::[] ->  print_endline hd
  | hd :: tl -> print_endline hd  ; printlist tl;;

However, as soon as I switch to printf, it doesn't work anymore. What's wrong with my printf version?

let rec printlist strlist =
  match strlist with 
  | [] ->  printf "" 
  | hd::[] ->  printf hd
  | hd :: tl -> printf "%s\n" hd  ; printlist tl;;
Error: This expression has type
         (unit, out_channel, unit) format =
           (unit, out_channel, unit, unit, unit, unit)
           CamlinternalFormatBasics.format6
       but an expression was expected of type string

Upvotes: 1

Views: 3257

Answers (2)

Richard-Degenne
Richard-Degenne

Reputation: 2949

In addition to Jeffrey's answer, I would suggest you use the standard library more in order to write more concise code.

List.iter, for example, calls a given function on all the elements of the list:

let print_list l = List.iter (fun e -> Printf.printf "%s\n" e) l

Using partial application smartly, you can make this line even shorter and more readable:

let print_list = List.iter (Printf.printf "%s\n")

The only difference with your function is the newline after the last element.


On the other hand, instead of printing elements one after another, a more functional and idiomatic approach would be to build the whole string first, and then print it.

Lucky you, the standard library got you covered. String.concat joins the elements in a string list together in one big string. You can also specify a string to use as a separator, and you don't have to worry about the newline after the last element.

let print_list l = print_string (String.concat "\n" l)

Upvotes: 1

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66808

In essence, you're trying to use printf without a format. The first argument of printf has to be a constant string. So you should have this:

printf "%s" hd

rather than this:

printf hd

To see why this is required, imagine what would happen if some of the strings in your input contained percent characters. Things would get out of control (type-wise) quite quickly.

Upvotes: 2

Related Questions