【问题标题】:Why prefer currying to tuple arguments in OCaml?为什么在 OCaml 中更喜欢柯里化而不是元组参数?
【发布时间】:2012-05-26 20:54:24
【问题描述】:

"Introduction to Caml"

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

'a -> 'b -> 'c 调用约定与'a * 'b -> 'c 进行比较时。

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

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

【问题讨论】:

  • Caml-light 及后续版本中大部分函数的柯里化选择在报告“ZINC 实验:ML 语言的经济实现”中进行了说明。我记得的一件事是,使用适当的评估方案(在报告中描述),一个柯里化函数不需要分配就可以被调用。 caml.inria.fr/pub/papers/xleroy-zinc.ps.gz
  • @PascalCuoq,而一个元组需要被分配、解包,然后 GCed?
  • 这是另一个问题,但要回答,不,你不应该。上次我检查它甚至没有优化a, bmatch a, b with x, y -> ... 中的分配。如果您想自己检查,我发现阅读ocamlopt -S 生成的x86 程序集对我来说很方便,因为我不必学习新的表示。
  • 需要明确的是,元组函数通常不需要在针对它们进行优化的编译器中进行分配,在大多数 SML 实现中都是如此。作为标准展平优化的一部分,N 元参数/结果元组通常编译为 N 个参数/结果。仅当以一流的方式给出或使用参数/结果元组时,才会发生额外的装箱/拆箱(即恰好在您无法以咖喱形式表达的情况下)。
  • 帕斯卡,你的第一条评论很有趣,来源丰富,是安德烈亚斯回答的绝佳补充。您为什么不将其发布为答案?我很确定match a,b with x,y -> ... 已经过优化;事实上,我们最近甚至讨论了此优化的an extension,欢迎对此提供反馈。

标签: ocaml tuples currying


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 我认为这不再是真的。 "OCaml is smarter than I thought" 说“我阻止了内联,但仍然没有分配!为什么?嗯,事实证明 OCaml 可以优化一个元组获取函数来获取通过寄存器传入的元组元素,这正是发生了什么。编译器再次意识到不需要分配。”
    【解决方案3】:

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

    【讨论】:

    • 好点。还有另一个选择是在其中的实例:数据类型构造函数。在 SML 中它们是元组的,在 Haskell 中它们是咖喱的。奇怪的是,在 OCaml 中它们是元组的,这与语言的其余部分有点不匹配。
    • 数据类型构造函数被元组化的更深层含义是元组是一个匿名的特殊情况数据构造函数。
    猜你喜欢
    • 1970-01-01
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多