12

“Caml 简介”

请注意,在 Caml 中,最好将 Curried 函数定义用于多参数函数,而不是元组。

'a -> 'b -> 'c调用约定与'a * 'b -> 'c.

在使用 SML/NJ 时,我习惯于对输入和输出都使用元组类型:('a * 'b) -> ('c * 'd)所以使用元组来表达多个输入似乎与我表达多个输出的方式是对称的。

为什么对元组参数的 OCaml 函数声明建议使用柯里化?仅仅是允许柯里化/部分评估带来的更大灵活性,还是从 OCaml 编译器的实现细节中获得的其他好处?

4

3 回答 3

8

我认为很多都是约定俗成的——OCaml 中的标准库函数是柯里化的,而在标准 ML 中它们通常不是除了一些高阶函数。但是,语言中存在一个差异:运算符(例如(*))在 OCaml 中被柯里化(例如int -> int -> int);而它们在标准 ML 中是 uncurried 的(例如op*can be (int * int) -> int)。正因为如此,内置的高阶函数(例如 fold)也采用在 OCaml 中柯里化而在标准 ML 中未柯里化的函数;这意味着要让您的函数使用它,您需要遵循各自的约定,并且从那里开始。

于 2012-05-20T08:27:11.777 回答
5

是的,主要是符号的方便和部分应用的灵活性。Curried 函数在 OCaml 中是惯用的,编译器可能会比元组函数更好地优化它们(而 SML 编译器通常针对元组进行优化)。

元组的优点是您提到的参数/结果对称性(在组合函数时特别有用),也许还有符号熟悉度(至少对于来自非函数世界的人来说)。

于 2012-05-19T16:34:02.013 回答
3

关于 OCaml 中的优化的一些评论。

在 OCaml 中,我注意到在将元组作为参数传递时总是分配元组。即使在 ocaml 中在主堆中分配速度很快,当然也比什么都不做要长。因此,每次您将元组作为参数传递时,都会花费一些时间来分配和填充元组。

我预计 ocaml 编译器会优化不需要构建元组的情况。例如,当您内联被调用函数时,您可能只使用元组组件而不使用元组本身。因此元组可以被忽略。不幸的是,在这种情况下,OCaml 不会删除无用的元组并仍然执行分配。出于这个原因,在代码的关键部分使用元组可能不是一个好主意。

于 2012-05-19T19:10:59.367 回答