代码之家  ›  专栏  ›  技术社区  ›  齐天大圣

OCaml:使用核心集添加元素的惯用方法是什么?

  •  3
  • 齐天大圣  · 技术社区  · 9 年前

    在标准库中, add 函数具有以下签名:

    val add : elt -> t -> t
    

    所以我可以用管道操作符添加元素:

    Set.empty |> add elt1 |> add elt2
    

    然而,当我切换到Core时,我注意到add的签名已变成:

    val add : ('a, 'cmp) t -> 'a -> ('a, 'cmp) t
    

    现在set成为第一个参数。旧的管道样式不再适用于它。

    使用核心集添加元素的惯用方法是什么?

    3 回复  |  直到 9 年前
        1
  •  3
  •   Michaël Le Barbier    9 年前

    不要使用管道混淆函数应用程序!

    管道存在有很好的理由,即构建管道,但在您的示例中,您只是在滥用和混淆代码。

    如果您只想将两个元素添加到一个集合中,只需编写

    Set.(add (add empty a) b)
    

    它非常干净,字迹清晰。如果要添加更多元素, 您可以通过使用fold函数来提高可读性:

    List.fold_left Set.add Set.empty [a; b; c; d; e; f]
    

    我们可以推测简街改变了 Set.add 精确地用于 List.fold_left 它是尾部递归的,而 List.fold_right 应该与标准库中的集合一起使用的不是尾部递归。

        2
  •  2
  •   Ashish Agarwal    9 年前

    Jane Street解释了这一设计选择 blog post 作为 t comes first 规则基本上,问题是没有好的选择。有时,拥有 t 先来,有时最后。也许他们选择的主要好处是这是一个决定。正如他们在引言中所说的,有时候一个决定的好处是避免浪费时间去思考这个问题。

    更直接地回答你的问题,我想说,这没有惯用的解决方案。写你觉得直观的东西。在其他答案中已经给了你一些建议。不要辱骂管道操作员。使用 fold 如果有更多的项目要添加。我会避免 flip ; 你混淆了代码,但没有使其更简洁(但我有时也会使用它)。

    最后,请注意 Core 使用带标签的参数的附加设计选择通常可以完全解决问题。例如,他们 List.fold 也需要 t型 第一个,但其他参数被标记。因此,您可以将 t型 无论你想去哪里 列表.fold 可用于管道和非管道。所以有人会问他们为什么不在 Set.add t -> elt:elt -> t 嗯,标签也是额外的开销;它们会让你键入更多的字符。在任何地方使用它们都是极端的,他们认为这个功能在没有标签的情况下更好。

        3
  •  1
  •   Jeffrey Scofield    9 年前

    在玩了几分钟之后,我能想到的最好的办法就是 flip 以反转参数顺序。

    let flip f a b = f b a
    

    然后你可以写:

    Set.empty |> flip add elt1 |> flip add elt2
    

    上次我检查的时候, 轻弹 在Core中可用 Fn.flip .

    (一般来说,没有参数顺序在所有情况下都是最佳的。您可能最终会认为核心顺序对某些事情来说确实很好。)