OCaml 参数传递方案中的断点

Breakpoints in the argument-passing scheme of OCaml

今天,我正在查看 Jane Street's Core_kernel module and I came across compose 函数的源代码:

(* The typical use case for these functions is to pass in functional arguments
   and get functions as a result. For this reason, we tell the compiler where
   to insert breakpoints in the argument-passing scheme. *)
let compose f g = (); fun x -> f (g x)

我会将 compose 函数定义为:

let compose f g x = f (g x)

他们给出这样定义 compose 的原因是“因为 compose 是一个以函数 fg 作为参数的函数,并且 returns 函数 fun x -> f (g x) 结果,他们定义了 compose 他们告诉编译器在 fg 之后但在 [=23] 之前插入断点的方式=] 在参数传递方案中。”

所以我有两个问题:

  1. 为什么我们需要在参数传递方案中设置断点?
  2. 如果我们以正常方式定义 compose 会有什么不同?

来自 Haskell,这个约定对我来说没有任何意义。

这是一种效率技巧,可以避免评论中指出的预期用例中部分应用程序的成本。

OCaml 将柯里化函数编译成固定元数结构,并在必要时使用闭包部分应用它们。这意味着该参数的调用是高效的——没有闭包构造,只有函数调用。

对于fun x -> f (g x)compose中的闭包构造,但这将比部分应用更有效。由部分应用程序生成的闭包通过一个包装器 caml_curryN 来确保效果在正确的时间发生(如果该闭包本身是部分应用的)。

编译器选择的固定元数是基于简单的句法分析——本质上是连续接受多少个参数,中间没有任何参数。 Jane St. 程序员通过注入 () "in between" 个参数,将其用于 select 他们想要的参数。

简而言之,let compose f g x = f (g x) 是一个不太理想的定义,因为它会导致常见的双参数情况 compose f g 成为更昂贵的部分应用程序。

在语义上,当然,完全没有区别。

值得注意的是,部分应用程序的编译在 OCaml 中得到了改进,不再需要这种性能破解。