Scanf does not accept first arg

The following code works without errors:

let fxy = print_int (max xy); 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 the fmt variable to store the format "\ n% d% d" and pass it to scanf, I get an error message, here is the new code:

 let fxy = print_int (max xy); 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 a difference between the two codes?

+4
source share
2 answers

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

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

Change the line let fmt = as follows:

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

This makes your code work for me.

+4
source

Oddly enough, this is actually a value-added function: the scan functions are checked by type at compile time, and for this the compiler should be able to clearly see the format string when called and make sure that no fraud occurs with it. Such fraud can lead to unwanted behavior, 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 ab -> a,b) (* the compiler cannot infer a type for `b` *) 
+2
source

All Articles