12

在获取 Array、List 或 Seq 的第 N 个元素的函数中使用不同的参数顺序是否有充分的理由:

Array.get source index
List .nth source index
Seq  .nth index  source

我想使用管道运算符,似乎只有 Seq 才有可能:

s |> Seq.nth n

有没有办法与 Array 或 List 具有相同的符号?

4

3 回答 3

15

我想不出任何好的理由来定义Array.get这种List.nth方式。鉴于流水线在 F# 中非常常见,因此应该将它们定义为source最后出现的参数。

在 的情况下List.nth,它不会有太大变化,因为您可以使用Seq.nth并且时间复杂度仍然O(n)n列表的长度:

[1..100] |> Seq.nth 10

Seq.nth在数组上使用不是一个好主意,因为您会丢失随机访问。为了保持O(1)的运行时间Array.get,您可以定义:

[<RequireQualifiedAccess>]
module Array =
    /// Get n-th element of an array in O(1) running time
    let inline nth index source = Array.get source index

一般来说,不同的参数顺序可以通过使用flip函数来缓解:

let inline flip f x y = f y x

您可以直接在上面的功能上使用它:

[1..100] |> flip List.nth 10
[|1..100|] |> flip Array.get 10

    

于 2013-03-03T11:29:12.880 回答
7

只需使用反向管道运算符:

[1..1000] |> List.nth <| 42

由于两个运算符都是左关联的,x |> f <| y因此被解析为(x |> f) <| y,这样就可以了。

如果要删除括号,后向管道运算符也很有用:f (very long expression)可以替换为f <| very long expression.

于 2013-03-03T23:14:13.510 回答
5

由于 Pad 和 bytebuster 回答了您的最后一个问题,我将重点介绍为什么部分。

这是基于我目前的知识,而不是历史事实。

由于从 OCaml 和 OCaml 派生的 F# 具有ArrayList没有 Seq,并且 F# 使用 |> 进行自然流水线和类型检查,并且OCaml 缺少 pipleline operator,因此 F# 的作者切换到 Seq。但显然为了与 OCaml 向后兼容,他们并没有切换所有内容。

于 2013-03-04T00:03:10.337 回答