Почему это не закорачивает отрывок OCaml с работой Printf.printf?

Я - новичок 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" работа тогда?

Что продолжается?

9
задан dimatura 5 March 2010 в 18:16
поделиться

2 ответа

В OCaml существует своего рода «перегрузка» значения строковых литералов. Во время компиляции они могут интерпретироваться либо как строка, либо как формат (что совершенно разные вещи в системе типов), в зависимости от того, что думает проверяющий типы.Если он решает, что это должен быть формат, тогда строка формата анализируется непосредственно во время компиляции (именно поэтому он может проверять типы аргументов printf во время компиляции). (В отличие от C, который анализирует строку во время выполнения.) Однако нет простого способа преобразовать строку в формат во время выполнения. Поэтому, когда вы видите Printf.printf «2.5», «2.5» на самом деле не является строкой, а представляет собой специальный тип формата, который был проанализирован во время компиляции. Вот почему вы не можете заменить его строкой.

С другой стороны, если вы просто хотите напечатать строку, вы можете использовать print_string (или print_endline , если вам нужна новая строка).

15
ответ дан 4 December 2019 в 11:41
поделиться
Printf.printf "%s" anyStringExpr

будет работать. Первый аргумент printf является несколько магическим. (Подробности уточнят другие.)

3
ответ дан 4 December 2019 в 11:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: