保证在OCaml中赋值给函数的返回值

时间:2010-09-12 23:21:28

标签: functional-programming ocaml variable-assignment

从Lisp来到OCaml,我发现自己对函数何时返回以及何时不返回感到非常困惑。我想念我的魔术报价!值得庆幸的是,大多数时候,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

告诉我开始和结束都绑定到Sys.time,而不是Sys.time的返回值。

这种行为我是不是想尝试不是OCamly?我想以另一种方式做事吗?我只是遗漏了一些完全明显的东西吗?

3 个答案:

答案 0 :(得分:10)

将函数应用于参数时,将评估函数。即当您执行f时,f永远不会被评估。当您执行f x时,f始终会得到评估。它没什么神奇之处。

正如您正确指出的那样,Sys.time是一个函数(类型为unit -> float),而let start = Sys.time只是将该函数指定给start

要获得您想要的行为,只需执行let start = Sys.time (),它将函数Sys.time应用于参数()(这是类型unit的唯一值)。< / p>

答案 1 :(得分:3)

只能通过编写名称来调用函数。如果你只是写一个函数的名字,你将返回函数本身,而不是它的返回值。该错误告诉您函数采用unit参数 - 即,您应该编写Sys.time ()来实际应用函数并获得结果float值。

答案 2 :(得分:0)

为了帮助人们习惯使用Lisp,我想说OCAML中只有两个评估规则:

  • 延迟评估规则:未应用于任何参数的函数值(例如fun x -> body)将不再进行评估。 (函数体的评估是“延迟的”。)而是将表达式“body”编译成计算机代码。该计算机代码是函数表达式的真正“值”,只要函数应用于参数,代码就会运行。
  • 热切评估规则:在评估f x时,首先评估参数x。 (函数“渴望评估它们的参数”。)然后计算函数表达式f,它通常产生一个函数值,例如fun x -> body。 (这里,body尚未评估;只有在评估我们得到函数值fun x -> body时才会这样做。例如,f可能是一个复杂的表达式,它产生如下函数值:结果。)最后,结果函数的主体应用于参数的实际计算值(即body被评估,x被参数的计算值替换。)

出于这个原因,你可以在OCAML中实现“quote”,如果你想延迟某些表达式的评估,只需将它放在函数表达式的主体中。例如,如果您之前已根据f计算let f = fun x->x+1,现在您想延迟f 3的评估,则可以将此f 3放入函数体中:

 let delay_f () = f 3;;

现在,只有在评估delay_f ()时才会获得4。您可以将值delay_f传递给另一个函数,f 3将保持无评估,直到有人评估delay_f ()