2010-09-12 1 views
6

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

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 

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

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

ответ

10

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

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

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

3

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

0

Чтобы помочь людям использовать для Lisp, я бы сказал, что есть только два правила оценки в 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().

 Смежные вопросы

  • Нет связанных вопросов^_^