在获取 Array、List 或 Seq 的第 N 个元素的函数中使用不同的参数顺序是否有充分的理由:
Array.get source index
List .nth source index
Seq .nth index source
我想使用管道运算符,似乎只有 Seq 才有可能:
s |> Seq.nth n
有没有办法与 Array 或 List 具有相同的符号?
我想不出任何好的理由来定义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
只需使用反向管道运算符:
[1..1000] |> List.nth <| 42
由于两个运算符都是左关联的,x |> f <| y
因此被解析为(x |> f) <| y
,这样就可以了。
如果要删除括号,后向管道运算符也很有用:f (very long expression)
可以替换为f <| very long expression
.
由于 Pad 和 bytebuster 回答了您的最后一个问题,我将重点介绍为什么部分。
这是基于我目前的知识,而不是历史事实。
由于从 OCaml 和 OCaml 派生的 F# 具有Array和List但没有 Seq,并且 F# 使用 |> 进行自然流水线和类型检查,并且OCaml 缺少 pipleline operator,因此 F# 的作者切换到 Seq。但显然为了与 OCaml 向后兼容,他们并没有切换所有内容。