代码之家  ›  专栏  ›  技术社区  ›  dimatura

为什么这个带有printf.printf的短ocaml片段不起作用?

  •  9
  • dimatura  · 技术社区  · 14 年前

    我是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!" 做。当我付出 “你好!” 进入之内 Printf.printf 它工作 果不其然。当我付出 浮点数的字符串_(平均1。4) 打印f.printf 它失败了,告诉我们 我没想到会有一个字符串,而是另一个奇怪的类型。但是为什么呢 “你好!” "2.5" 然后工作?

    发生什么事?

    2 回复  |  直到 14 年前
        1
  •  15
  •   newacct    14 年前

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

    在不相关的注释上,如果只想打印字符串,则可能需要使用 print_string (或) print_endline 如果你想换行的话)。

        2
  •  3
  •   Brian    14 年前
    Printf.printf "%s" anyStringExpr
    

    会工作。printf的第一个论点有点不可思议。(其他人将填写详细信息。)