【问题标题】:Guarantying assignment to a function's return value in OCaml在 OCaml 中保证对函数返回值的赋值
【发布时间】:2011-04-11 10:57:45
【问题描述】:

从 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

告诉我 start 和 end 绑定到 Sys.time,而不是 Sys.time 的返回值。

我想要避免的这种行为不是 OCamly 吗?我想以另一种方式做事吗?我只是错过了一些非常明显的东西吗?

【问题讨论】:

    标签: functional-programming ocaml variable-assignment


    【解决方案1】:

    当您将函数应用于参数时,它会被评估。 IE。当您执行f 时,f 永远不会被评估。当您执行f x 时,f 总是会被评估。它没有什么神奇之处。

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

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

        因此,您可以在 OCAML 中实现“引用”,如果您想延迟某个表达式的计算,只需将其放在函数表达式的主体中即可。例如,如果您之前通过let f = fun x->x+1 计算了f,现在您想延迟对f 3 的评估,您可以将这个f 3 放入函数体中:

         let delay_f () = f 3;;
        

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

        【讨论】:

          猜你喜欢
          • 2012-06-16
          • 2019-01-05
          • 2011-09-15
          • 1970-01-01
          • 2020-09-08
          • 2018-04-06
          • 1970-01-01
          • 2013-04-08
          • 2020-09-21
          相关资源
          最近更新 更多