Why does this behavior occur?
# Printf.sprintf ("Foo %d %s") 2 "bar";;
- : string = "Foo 2 bar"
# Printf.sprintf ("Foo %d" ^ " %s") 2 "bar";;
Printf.sprintf ("Foo %d" ^ " %s") 2 "bar";;
Error: This expression has type string but an expression was expected of type
('a -> 'b -> 'c, unit, string) format =
('a -> 'b -> 'c, unit, string, string, string, string) format6
I would expect that the string concatenation would be evaluated first, so everything will proceed as normal. Does this have to do with the type system trickery that Printf employs?
Yes, it has to do with type system trickery. If you want to create a format string you need to use the (^^) operator:
# Printf.sprintf ("Foo %d" ^^ " %s") 2 "bar";;
- : string = "Foo 2 bar"
I'm not deeply schooled in this trickery, but I believe that the compiler is willing to promote a string constant to a printf format if the typing context calls for it. However, the result of ("Foo %d" ^ " %s")
is not a string constant, so it doesn't get promoted. The (^^) operator creates a typing context where both operands can be promoted if they are string constants.
You can see why it would have to be a string constant: otherwise the associated types (of the values to be printed) can't be determined.