获取Array,List或Seq的第N个元素的不同参数顺序

Pau*_*zak 12 f# pipeline

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

Array.get source index
List .nth source index
Seq  .nth index  source
Run Code Online (Sandbox Code Playgroud)

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

s |> Seq.nth n
Run Code Online (Sandbox Code Playgroud)

有没有办法与Array或List使用相同的表示法?

pad*_*pad 15

我认为没有任何合理的理由来定义Array.getList.nth这种方式.鉴于在F#中管道输出很常见,它们应该被定义,以便source参数最后出现.

在这种情况下List.nth,它没有太大变化,因为你可以使用Seq.nth和时间复杂性仍然O(n)n列表的长度:

[1..100] |> Seq.nth 10
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

通常,使用flip函数可以减轻不同的参数顺序:

let inline flip f x y = f y x
Run Code Online (Sandbox Code Playgroud)

您可以直接在上面的函数中使用它:

[1..100] |> flip List.nth 10
[|1..100|] |> flip Array.get 10
Run Code Online (Sandbox Code Playgroud)

    


byt*_*ter 7

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

[1..1000] |> List.nth <| 42
Run Code Online (Sandbox Code Playgroud)

由于两个运算符都是左关联的,因此x |> f <| y被解析为(x |> f) <| y,这就是诀窍.

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

  • 这样做,但我不喜欢它的可读性 - 非常幽闭恐怖! (3认同)
  • +1`not`和`defaultArg`使我习惯使用`<|`; 一旦你习惯它,它似乎并不那么尴尬. (2认同)

Guy*_*der 5

由于Pad和bytebuster回答了你的最后一个问题,我将专注于为什么部分.

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

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