什么是F#缺乏OO或势在必行?

很多时候我听说F#不适合特定的任务,比如UI。 “使用正确的工具”是一个常见的短语。

除了缺少WinForms / WPF / ORM设计器等工具之外,我不确定F#到底缺少什么 – 老实说! 然而,特别是在UI方面,我被告知C#做得更好。 那么,在强制使用F#时,F#的实际差异和遗漏是什么?

这是我提出的列表:

  • 大量缺少工具支持

  • F#仍然是测试版

  • 你的开发人员不知道F#

    • 我不想考虑这些要点,因为它们并不是F#的内在特征。
  • Mutable需要“可变”或需要ref,ref需要! 解除引用

  • Mutables赋值< – 和ref使用:=(它们都是1个字符而不仅仅是=)

  • val需要DefaultValueAttribute来获取默认值

  • F#不会发出隐式接口

  • 受保护的成员更难以处理

  • 没有自动属性

  • 抽象类上实现的虚拟成员需要两个定义

  • 引用到LINQ-Expression-Trees会产生与C#/ VB略有不同的树(对于期望以特定格式表达其表达式的API而言很烦人)

  • 没有stackalloc

  • F#没有?:条件运算符

  • F#中的指针可能被认为更麻烦

  • 代表/事件可能被认为更加繁琐(我认为它们更容易,但至少它们是不同的)

  • 没有自动类型转换(比如int to float或者隐式转换)

  • Nullable没有特殊的语法支持(C#的?类型注释和??运算符,以及在nullable上使用运算符。)

  • 没有自动向上扩展到普通基类或装箱(例如:让x:obj =如果为真,那么其他为“hi”//这不会是类型检查)

  • 没有警告就不能丢弃值(“忽略”以绕过它)

  • 没有C风格的语法:)

问题:哪些是编写命令式或OO代码的障碍? 为什么(简短的例子)? 我错过了哪些? 什么是最好的解决方法,为什么他们还不够?

请注意 ,我不是在谈论编写所谓的惯用语F#,我当然不是在谈论函数式编程。 我更感兴趣的是“如果我要强迫自己在F#中编写UI或命令式/ OO代码,使用F#OO /命令式function和类类型,最痛苦的是什么?”

奖励如果您不了解F#但使用C#或VB.NET并认为它是某种情况下更好的工具,请指出您觉得有吸引力的特定语言function和语法。

关于OO的东西,我的清单可能是

  • 你提到了一些关于接口和虚拟的东西,可能是烦恼或障碍; 你提到的缺少自动道具也是一种耻辱
  • OO框架有时需要许多相互递归的类,F#当前强制您将其放入一个文件中(在’type …和…和…’块中)
  • 如果需要在派生类中调用两个不同的基本构造函数,则必须使用“显式”类语法(如此处所述)

也就是说,F#在OO部门也有优势,比如类型推断,本地function,简洁的语法……所以总的来说,我可以称它为“重度OO”部门。

(我几乎没有做任何类型的UI编程,所以没有资格在那里权衡。)

(编辑:我也想插入那个,即使你明确选择从问题中排除’工具’,我认为工具很重要,在这方面,其他管理的VS语言也很出色。)

我不是这个问题的忠实粉丝,因为它抱怨F#不支持惯用的C#。 例如,我认为批评F#使用< - 和:=进行变量赋值是不公平的,因为语言默认情况下会使事情不可变。

无论如何,你可以在C#中做几件必须/面向对象的事情,你根本不能在F#中做。

  • F#不支持嵌套类。 在C#中,您可以在另一个类的主体内声明一个类作为作用域类型的机制。 F#不支持此function。

  • F#不允许您两次实现相同的通用接口。 例如,在C#中,您可以在同一类型上实现IComparableIComparable

  • 在F#中,您必须具有架构层次。 由于F#的类型推断,您只能使用已在“之前”或类型声明的相同“块”中声明的类。 在C#中,您可以拥有任何其他类引用。 (这实际上强制执行一些好的编程实践。)

  • 对于LINQ,F#没有“本机”支持,因为没有来自关键字。 但是,您可以使用LINQ API和lambda表达式来实现相同的结果。

F#可以做的事情,C#不能:

  • 受歧视的工会。 这使得在F#中创建树状数据结构变得微不足道,在C#中,您必须求助于复杂的类型层次结构。

  • 异步工作流程。 F#库的这一特性通过抽象出与APM相关的所有痛苦,使异步和并行编程更加苍白。

  • 模式匹配和活动模式。

  • 用于消除与使用错误单元相关的错误的度量单位。 (例如,将“英尺”添加到“米”。)

  • 等等

你不应该关注F#’不能像C#那样做’,因为学习F#的全部意义在于提出一种思考解决问题的新方法。 如果你在F#中编写惯用的C#代码,你实际上并没有获得任何东西。

AFAIK F#不缺少.NET / COM互操作的任何“必备”。 在F#中,您可以执行诸如out和byref参数之类的操作,声明字符串文字,并支持将属性放在几乎任何内容上。

F#中的命令式编程比人们会让你相信要好得多。 F#的匹配声明很棒。 为什么其他语言没有实现它我不知道。 就语法(mutable,ref等)而言,它们很容易使用。 你被F#的稀疏性所破坏,当语法大于正常时,很容易抱怨。 元组也很棒。 他们也将在C#4.0中。 Currying是Imperative的另一个奖励。

关于面向对象,我发现我很少在纯F#项目中使用inheritance,而是喜欢使用组合和接口。 这主要是因为使用了主要的构造函数,允许您将它的参数用作方法中的私有属性(不确定我是否正确使用)。 其他语言结构(如模式匹配)也会使您远离inheritance。 我没有做任何混合项目C#/ F#所以我不能对此发表评论。

F#不是所有的玫瑰。

我对F#和游戏编程最大的问题是性能。 在F#中实现真的很快,我经常在我想到它的同时获得一个原型并运行我想要做的事情然而我发现自己为了性能原因而不是在C#中重写代码。

部分问题是我对函数式编程风格缺乏经验,即使用Seq,List,Map及其所有附带的方法,如map,iter,fold,scan。 我的第一个function解决方案几乎从来不是最快的,而我的第一个程序解决方案几乎总是接近最好的。 我想说这部分不是我。 在某些情况下,函数式编程不会使其自身具有性能。

我现在在F#中使用的function数据类型少于我开始时使用的function数据类型。

编辑:

自从我发布这篇文章以来,已经过去了好几个月,我不再遇到性能方面的问题。 我的第一个function解决方案现在通常更简单,几乎是最优的,并且不可变的数据结构很简单。 我现在唯一的性能问题是使用CLI,如果需要,我总是可以执行c ++ / cli。 我现在使用除了接口之外的一些inheritance,但它仅用于匿名对象。

静态类型函数语言最大的痛苦是无法在需要推断的方法上使用变量参数。 喜欢地图function。 在F#中你需要map2 map3等。

另一方面,C#也缺乏这一点,除非你想通过反思。

以Scheme为例,它不是静态类型的。 定义可以处理map_1 … map_n的所有情况的单个函数没有问题。 当然你放松了静态类型的安全性,但与编写简洁代码的额外方便性相比,它显得相形见绌。

只是为了记录:F#有堆栈分配 – 尝试无限递归,这不是尾递归,你会得到堆栈溢出。 除了你知道你可以安全地使用尾递归F#(在C#中它依赖)之外,它与C#中的堆栈分配没有什么不同。

另外,我要指出的是,当你遇到非常繁重的面向事件的代码时,F#在允许你建立一个框架来执行调度事件到处理程序等的“管道”方面比C#更好,而没有管道成为你的大部分代码。 对于简单的UI,C#或VB可能适合更多人。 对于复杂的情况,F#领先,我个人需要帮助处理复杂情况而不是简单情况。