我是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"
会起作用?
发生了什么事?
答案 0 :(得分:15)
在OCaml中存在一种字符串文字含义的“重载”。在编译时,它们可以被解释为字符串,也可以被解释为格式(类型系统中完全不同的东西),具体取决于类型检查器的想法。如果它确定它应该是一种格式,那么格式字符串将在编译时直接解析(这就是为什么它能够在编译时对printf的参数进行类型检查)。 (与C不同,后者在运行时解析字符串。)但是,没有简单的方法可以在运行时将字符串转换为格式。因此,当您看到Printf.printf“2.5”时,“2.5”实际上不是字符串,而是作为在编译时解析的特殊格式类型。这就是为什么你不能用字符串替换它。
在不相关的说明中,如果您只想打印字符串,则可能需要使用print_string
(或print_endline
如果您想要换行符。)
答案 1 :(得分:3)
Printf.printf "%s" anyStringExpr
会奏效。 printf的第一个参数有些神奇。 (其他人将填写详细信息。)