为什么这个简短的OCaml片段与Printf.printf不起作用?

时间:2010-03-05 18:16:15

标签: printf ocaml

我是OCaml的新手。我正在玩“你好世界”类型的片段,并遇到了这种情况。 这是一个与翻译的会话,还有一些额外的评论:

# let average a b = 
  (a +. b) /. 2.;;
val average : float -> float -> float = <fun>
# average 1. 4.;;
- : float = 2.5
# string_of_float (average 1. 4.);;
- : string = "2.5"

(* this fails...*)
# let _ = Printf.printf (string_of_float (average 1. 4.));;
Error: This expression has type string but an expression was expected of type
         ('a, out_channel, unit) format =
           ('a, out_channel, unit, unit, unit, unit) format6

(* yet this works *)
# "hello!";;
- : string = "hello!"
# let _ = Printf.printf "hello!";;
hello!- : unit = ()

(* another failed attempt *)
# let s = string_of_float (average 1. 4.);;
val s : string = "2.5"
# s;;
- : string = "2.5"
# let _ = Printf.printf s;;
Error: This expression has type string but an expression was expected of type
         ('a, out_channel, unit) format =
           ('a, out_channel, unit, unit, unit, unit) format6

(* and this also works?? *)
# let _ = Printf.printf "2.5";;
2.5- : unit = ()

所以这就是情况。 string_of_float (average 1. 4.)返回一个字符串, 就像"hello!"一样。当我将"hello!"提供给Printf.printf时,它就可以了 正如所料。当我将string_of_float (average 1. 4.)提交给Printf.printf时,它会失败并告知 我预计不会期待一个字符串,但其他奇怪的类型。但为什么"hello!""2.5"会起作用?

发生了什么事?

2 个答案:

答案 0 :(得分:15)

在OCaml中存在一种字符串文字含义的“重载”。在编译时,它们可以被解释为字符串,也可以被解释为格式(类型系统中完全不同的东西),具体取决于类型检查器的想法。如果它确定它应该是一种格式,那么格式字符串将在编译时直接解析(这就是为什么它能够在编译时对printf的参数进行类型检查)。 (与C不同,后者在运行时解析字符串。)但是,没有简单的方法可以在运行时将字符串转换为格式。因此,当您看到Printf.printf“2.5”时,“2.5”实际上不是字符串,而是作为在编译时解析的特殊格式类型。这就是为什么你不能用字符串替换它。

在不相关的说明中,如果您只想打印字符串,则可能需要使用print_string(或print_endline如果您想要换行符。)

答案 1 :(得分:3)

Printf.printf "%s" anyStringExpr

会奏效。 printf的第一个参数有些神奇。 (其他人将填写详细信息。)