今天在看Jane Street的源码的Core_kernel
模块和我 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
是一个函数,它采用函数 f
和 g
作为参数并返回函数fun x -> f (g x)
结果,他们定义了compose
他们告诉编译器在 f
之后插入断点的方式和 g
但在 x
之前在参数传递方案中。”所以我有两个问题:
compose
会有什么不同?正常的方式? 来自 Haskell,这个约定对我来说没有任何意义。
最佳答案
这是一种效率技巧,可以避免在评论中指出的预期用例中部分应用程序的成本。
OCaml 将柯里化(Currying)函数编译成固定数量的构造,在必要时使用闭包部分应用它们。这意味着该数量的调用是有效的——没有闭包构造,只是一个函数调用。compose
内将有一个封闭结构对于 fun x -> f (g x)
,但这会比部分应用更有效。部分应用程序生成的闭包通过包装器 caml_curryN
它的存在是为了确保效果在正确的时间发生(如果该关闭本身已部分应用)。
编译器选择的固定数量是基于简单的句法分析 - 本质上,有多少个参数连续被采用,中间没有任何东西。 Jane St. 的程序员通过注入(inject) ()
使用它来选择他们想要的数量。 “介于两者之间”的论点。
简而言之,let compose f g x = f (g x)
是一个不太理想的定义,因为它会导致常见的两个参数情况 compose f g
是一个更昂贵的部分应用程序。
当然,语义上完全没有区别。
关于haskell - OCaml 参数传递方案中的断点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29191484/