4

The following code runs with no errors:

let f x y =
    print_int (max x y);
    print_char ' ';
    print_int (x + y) in
for i = 1 to Scanf.scanf "%d" (fun x -> x) do
    Scanf.scanf "\n%d %d" f;
    print_newline ();
done;

But when I declare a variable fmt to hold the format "\n%d %d" and pass it to scanf,I get an error,here is the new code:

let f x y =
    print_int (max x y);
    print_char ' ';
    print_int (x + y) in
let fmt = "\n%d %d" in (* added *)
for i = 1 to Scanf.scanf "%d" (fun x -> x) do
    Scanf.scanf fmt f; (* edited *)
    print_newline ();
done;

I get this error:

  File "prog.ml", line 7, characters 16-19:
  Error: This expression has type string but an expression was expected of type
     ('a, Scanf.Scanning.in_channel, 'b, 'c -> 'd, 'a -> 'e, 'e) format6

Why does it work differently?is there any difference between the two codes?

Redouane Red
  • 509
  • 1
  • 5
  • 13

2 Answers2

4

The handling of printf/scanf formats in OCaml uses some compiler magic that treats a string constant as a format in the proper context. The problem is that you no longer have a string constant.

You can pre-convert a string constant to a format using the format_of_string function.

Change your let fmt = line to this:

let fmt = format_of_string "\n%d %d" in

This makes your code work for me.

Jeffrey Scofield
  • 65,646
  • 2
  • 72
  • 108
2

As strange as it may seem, this is actually a value-added feature: scanning functions are type-checked at compile time, and in order to do this the compiler has to be able to clearly see the format string at the call site and make sure that no shenanigans are going on with it. Such shenanigans could lead to undesirable behaviour, as in the following example:

let fmt = "%d" in
let fmt' = fmt ^ (if input_type = "int" then " %d" else " %f") in
(* input_type is defined somewhere else in the program *)
(* the format string could now be either "%d %d" or "%d %f" *)
let a,b = Scanf.scanf fmt' (fun a b -> a,b)
(* the compiler cannot infer a type for `b` *)
chrismamo1
  • 917
  • 1
  • 7
  • 15