2012-08-01 33 views
7

我注意到静态方法在F#中比C#更受欢迎。在C#中,你总是一个元素通过调用一个实例方法添加到集合:F#编码风格 - 静态与实例方法

mySet.Add(elem); 

但在F#通常存在等效静态方法:

mySet.Add(elem) 
// OR 
Set.Add elem mySet 

我也看到了后者在样本中经常出现。在我看来,在语义上和功能上完全相同,但是来自C#背景,使用实例方法感觉更自然。 F#中哪种风格更好?为什么?

+0

相关:http://stackoverflow.com/q/7698133/162396 – Daniel 2012-08-01 19:24:03

+0

移动回答。 – 2012-08-01 19:40:46

+0

有许多原因,根源在于函数式编程作为一个整体,对于F#来说有一些特殊之处,很难知道从哪里开始进行验证。一旦你熟悉函数式编程,它就会变得很明显。 – Daniel 2012-08-01 21:27:53

回答

8

除了与类型推断相关的答案中提到的原因之外,在功能样式中更自然地发送函数作为参数。 如果它是一个实例方法,你将不得不写这样的事:

myHigherOrderFunction (fun (x:MyType) -> x.myFunctionAsMethod) 

但如果它被定义为一个静态方法,你可以这样写:

myHigherOrderFunction MyType.myFunctionAsMethod 

这是更优雅,更容易写(读取也是如此),并且与发送常规允许函数时的语法几乎相同。

一个实例方法需要一个类型的实例才能访问函数(方法),在OOP中,这不是一个问题,因为您认为在发送消息给对象但在FP中,函数单独(没有实例)是一等公民。

要访问一个静态方法,你需要指定Class,你可以将Class看作一种具有函数的容器(如模块或命名空间)。

+0

fp风格的优秀用例。在编程风格上,实例功能更短。 – nicolas 2012-08-04 13:51:14

0

在f#中,作为函数式语言的更原生的分离变量是不可变的,而函数是操作。这个功能类似于c#中的静态方法,但是对于c#方法,函数有一个优点。这是部分应用。您可以传递一些(而不是全部)参数的功能,并且这个函数的一部分参数将成为需要其他参数的新函数。

5

大多数标准F#类型是不可变的。当使用不可变对象的工作,静态方法更好的刻画是怎么回事,比如:

mySet.Add(elem); 

貌似mySet突变为包括elem,当F#集将返回一个新的mySet。幸运的是F#未能编译以确保你不犯这个错误,它仍然导致代码混淆。相反:

mySet |> Set.Add elm 

在形式上是截然不同的,看起来它会返回一些新的东西,而不会离原本太远。

2

尽管F#中的静态方法非常常见,但我发现实例方法对组件开发有很大意义。

原因? F#模块系统缺少函子。在其他类型的ML中,如SML或OCaml,您可以将组件作为简单模块进行开发。如果您稍后决定参数化模块,则可以将其提升为仿函数,而不必重写太多的源代码。在F#中你不能。

要在F#中创建一个参数化的“模块”,您必须求助于一个类并将您的方法转换为实例方法,并在实例构建期间传入参数。不幸的是,从一个模块到一个类涉及很多机械但令人讨厌的源代码更改。因此,硬核组件程序员可能会选择默认使用类和实例方法,就像在C#中一样。这让人联想到SML中有时采用的“只有函子式”风格。