我是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 = ()
Run Code Online (Sandbox Code Playgroud)
所以情况就是这样.string_of_float (average 1. 4.)返回一个字符串,就像那样"hello!".当我"hello!"投入时Printf.printf,它按预期工作.当我给string_of_float (average 1. 4.)到Printf.printf失败,并告诉我,它预计,没想到一个字符串,但其他的古怪的类型.但是,为什么"hello!"和"2.5"工作呢?
这是怎么回事?
new*_*cct 15
在OCaml中有一种字符串文字含义的"重载".在编译时,它们可以被解释为字符串,也可以被解释为格式(类型系统中完全不同的东西),具体取决于类型检查器的想法.如果它确定它应该是一种格式,那么格式字符串将在编译时直接解析(这就是为什么它能够在编译时对printf的参数进行类型检查).(与C不同,后者在运行时解析字符串.)但是,没有简单的方法可以在运行时将字符串转换为格式.因此,当您看到Printf.printf"2.5"时,"2.5"实际上不是字符串,而是作为在编译时解析的特殊格式类型.这就是为什么你不能用字符串替换它.
在一个不相关的说明中,如果您只想打印一个字符串,您可能想要使用print_string(或者print_endline如果您想要换行).