这个问题发生的范围比操作员要广泛得多^。基本上,OCaml 编译器需要知道您的格式字符串是文字字符串,并且需要在编译时知道文字字符串。否则,OCaml 无法在编译时将您的字符串转换为这种BLAHBLAH format6类型。该Printf模块仅适用于在编译时完全已知的格式字符串,或已转换为该BLAHBLAH format类型的格式字符串。
通常,您可以通过使用运算符并在代码中使用这些字符串之前^^将所有文字字符串显式转换为BLAHBLAH format类型来解决此问题。
这是另一个例子:
  # Printf.sprintf (if true then "%d" else "%d ") 2;;
  Error: This expression has type string but an expression was expected of type
     ('a -> 'b, unit, string) format =
       ('a -> 'b, unit, string, string, string, string) format6
  (* define a type abbreviation for brevity *)
  # type ('a,'b) fformat = ('a ->'b, unit, string) format;;
  type ('a, 'b) fformat = ('a -> 'b, unit, string) format
  # Printf.sprintf (if true then ("%d":('a,'b)fformat) else ("%d ":('a,'b)fformat)) 2;;
  - : string = "2"
OCaml 系统无法识别if ... then "a" else "b"可以转换为BLAHBLAH format. 如果您自己将每个文字字符串BLAHBLAH format转换为,那么一切正常。if/then/else(注意:如果您尝试将整个转换为,则它不起作用BLAHBLAH format,因为 OCaml 无法验证您的字符串是否为文字。)
问题的根源是类型安全的要求:OCaml 要求每个等都有一个正确类型的参数%d,并在编译时%s保证这一点。除非在编译时知道整个格式字符串,否则不能保证类型安全。因此,不可能使用通过复杂算法计算的格式字符串,例如通过随机选择和。PrintfPrintf%s%d
当我们if/then/else用来计算格式字符串时,然后是 OCaml 的东西,哎呀,这是一个复杂的算法,在编译时验证类型安全是没有希望的。^^运算符了解类型并在BLAHBLAH format连接格式字符串时产生正确的结果。但是if/then/else不知道BLAHBLAH format,并且没有内置的替代方法if/then/else(但我想你可以自己定义这样的东西)。