我对F#很新。我注意到的第一件事是收集操作被定义为函数而不是方法。
作为一项实验,我在list
上定义了几种方法:
type List<'a> with
member this.map f = List.map f this
member this.filter f = List.filter f this
然后,给这些帮手:
let square x = x * x
let isEven n = n % 2 = 0
这是使用这些方法的一个例子:
[1 .. 10].filter(isEven).map(square)
这是传统方式:
[1 .. 10] |> List.filter isEven |> List.map square
如此简洁明确不是选择函数而不是方法的理由。 : - )
从图书馆设计的角度来看,为什么选择函数而不是方法?
我的猜测是因为你可以传递List.filter
,但是除非它“绑定”到列表或包含在匿名函数中,否则无法真正传递filter
方法(即{ {1}}有效地将(fun (ls : 'a list) -> ls.filter)
方法转换回filter
)上的函数。
然而,即使有这个原因,似乎最常见的直接调用操作的情况会使方法更受欢迎,因为它们更简洁。所以我想知道是否还有其他原因。
编辑:
我的第二个猜测是功能专长。即专门化list
(例如List.filter
)非常简单。必须定义let evens List.filter isEven
方法似乎更加冗长。
答案 0 :(得分:5)
对于方法有哪些功能是功能专用化和易于分解的功能。
这是涉及函数的示例表达式:
let square x = x * x
let isEven n = n % 2 = 0
[1 .. 10] |> List.filter isEven |> List.map square
让我们分解一个名为evens
的函数来过滤均衡:
let evens = List.filter isEven
现在让我们分解出一个对整数列表进行平方的函数:
let squarify = List.map square
我们原来的表达现在是:
[1 .. 10] |> evens |> squarify
现在让我们回到基于原始方法的表达式:
[1 .. 10].filter(isEven).map(square)
在这种情况下,将平均值上的过滤器分解出来并非易事。
答案 1 :(得分:4)
我认为你的猜测是正确的。除了简洁之外,能够将List.filter
视为可以传递的第一类(您的第一个猜测)和部分应用(您的第二次猜测)是关键。这是一种动词而不是以名词为导向的观察世界的方式。我想Steve Yegge said it best:)