Гарантированное присвоение возвращаемого значения функции в OCaml - PullRequest
6 голосов
/ 13 сентября 2010

Приходя в OCaml из Lisp, я очень растерялся, когда функции возвращаются, а когда нет.Я скучаю по своей волшебной цитате!К счастью, в большинстве случаев OCaml автоматически знает, когда я хочу оценить функцию, а когда нет.Однако я часто пытаюсь присвоить возвращаемое значение функции в выражении let, как показано ниже:

let start = Sys.time in
(*
 * do something here
 *)
 ;
let ending = Sys.time in
Printf.printf "did something in %f seconds\n" (ending -. start)

, но затем ocamlc жалуется

Error: This Expression has type unit -> float
       but an expression was expected of type float

, сообщая, что началои end связаны с Sys.time, а не с возвращаемым значением Sys.time.

Это поведение, которое я пытаюсь получить, не OCamly?Хочу ли я делать вещи по-другому?Я просто упускаю что-то совершенно очевидное?

Ответы [ 3 ]

10 голосов
/ 13 сентября 2010

Функция оценивается, когда вы применяете ее к аргументу.Т.е. когда вы делаете f, f никогда не оценивается.Когда вы делаете f x, f всегда оценивается.В этом нет ничего волшебного.

Как вы правильно заметили, Sys.time - это функция (типа unit -> float), а let start = Sys.time просто назначает эту функцию start.

Чтобы получить требуемое поведение, просто выполните let start = Sys.time (), который применяет функцию Sys.time к аргументу () (который является единственным значением типа unit).

3 голосов
/ 13 сентября 2010

Вы не можете вызвать функцию, просто написав ее имя.Если вы просто пишете имя функции, вы возвращаете саму функцию, а не ее возвращаемое значение.Эта ошибка говорит вам, что функция принимает аргумент unit - то есть вы должны написать Sys.time (), чтобы фактически применить функцию и получить результирующее значение float.

0 голосов
/ 27 апреля 2012

Чтобы помочь людям, привыкшим к Лиспу, я бы сказал, что в OCAML есть только два правила оценки:

  • Правило отложенной оценки : значение функции, например fun x -> body, когда не применяется ни к какому аргументу, больше не будет оцениваться.(Оценка тела функции «задерживается».) Вместо этого выражение «тело» компилируется в компьютерный код.Этот компьютерный код является реальным «значением» выражения функции, и этот код будет запускаться всякий раз, когда функция применяется к аргументу.
  • Правильное правило оценки : При оценке f xаргумент x вычисляется первым.(Функции «стремятся оценить свои аргументы».) Затем вычисляется выражение функции f, которое обычно выдает значение функции, такое как fun x -> body.(Здесь body еще не вычисляется; оценивается только столько, сколько мы получаем значение функции fun x -> body. Например, f может быть сложным выражением, которое в результате выдает такое значение функции.) Наконец,тело результирующей функции применяется к фактически вычисленному значению аргумента (т. е. body оценивается с x, замененным вычисленным значением аргумента).

По этой причинеВы можете реализовать «кавычку» в OCAML, если вы хотите отложить оценку некоторого выражения, только поместив его в тело выражения функции.Например, если вы ранее вычислили f по let f = fun x->x+1 и теперь хотите отложить оценку f 3, вы можете поместить это f 3 в тело функции:

 let delay_f () = f 3;;

Теперь вы получите 4 только при оценке delay_f ().Вы можете передать значение delay_f другой функции, и f 3 останется без оценки, пока кто-нибудь не оценит delay_f ().

...