我多次听说F#不适合特定任务,例如UI。 “使用正确的工具”是一个常见的短语。
除了缺少WinForms / WPF / ORM设计器等工具之外,我不确定F#究竟缺少什么 - 老实说!然而,特别是在UI方面,我被告知C#做得更好。那么,在强制使用F#时,F#的实际差异和遗漏是什么?
以下是我提出的清单:
大量缺少工具支持
F#仍处于测试阶段
您的开发人员不知道F#
Mutables需要“可变”或需要ref,ref需要!取消引用
Mutables赋值为< - 和ref使用:=(他们都是1个字符而不仅仅是=)
val需要DefaultValueAttribute来获取默认值
F#不会发出隐式接口
受保护的成员更难以处理
无自动属性
在抽象类上实现虚拟成员需要两个定义
引用到LINQ-Expression-Trees会产生与C#/ VB略有不同的树(对于希望以特定格式表达其表达式的API而言很烦人)
没有stackalloc
F#没有?:条件运算符
在F#
代表/活动可能会被认为更加繁琐(我认为它们更容易,但至少它们是不同的)
没有自动类型转换(例如int to float或者隐式转换)
Nullable没有特殊的语法支持(C#的?类注释和??运算符,以及在nullables上使用运算符。)
没有自动向上扩展到普通基类或装箱(例如:让x:obj =如果为真,则为1,否则为“hi”//这不会是类型检查)
没有警告就不能丢弃值(“忽略”以解决它)
没有C风格的语法:)
问题:哪些是编写命令式或OO代码的障碍?为什么(简短的例子)?我错过了哪些?什么是最好的解决方法,为什么它们还不够?
请注意,我不是在谈论编写所谓的惯用语F#,我当然不是在谈论函数式编程。我更感兴趣的是“如果我要强迫自己在F#中编写UI或命令式/ OO代码,使用F#OO /命令式功能和类类型,最痛苦的是什么?”
加成 如果您不了解F#但使用C#或VB.NET并认为它是某种情况下更好的工具,请指出您觉得有吸引力的特定语言功能和语法。
答案 0 :(得分:10)
我不是这个问题的忠实粉丝,因为它抱怨F#不支持惯用的C#。例如,我认为批评F#使用< - 和:=进行变量赋值是不公平的,因为默认情况下语言会使事情不可变。
无论如何,你可以在C#中做几件必须/面向对象的事情,你根本不能在F#中。
F#不支持嵌套类。在C#中,您可以在另一个类的主体内声明一个类作为作用域类型的机制。 F#不支持此功能。
F#不允许您两次实现相同的通用接口。例如,在C#中,您可以在同一类型上实现IComparable<int>
和IComparable<string>
。
在F#中,您必须具有架构层次结构。由于F#的类型推断,您只能使用已在“之前”或类型声明的相同“块”中声明的类。在C#中,您可以拥有任何其他类引用。 (这实际上强制执行一些好的编程实践。)
F#没有对LINQ的“本机”支持,因为没有来自关键字。但是,您可以使用LINQ API和lambda表达式来实现相同的结果。
F#可以做的事情,C#不能:
受歧视的工会。这使得在F#中创建树状数据结构变得微不足道,在C#中,您必须求助于复杂的类型层次结构。
异步工作流程。 F#库的这一特性通过抽象出与APM相关的所有痛苦,使异步和并行编程更加苍白。
模式匹配和活动模式。
用于消除与使用错误单位相关的错误的度量单位。 (例如,将“英尺”添加到“米”。)
等
你不应该专注于F#'不能像C#那样做',因为学习F#的全部意义在于提出一种思考解决问题的新方法。如果你在F#中编写惯用的C#代码,你实际上并没有获得任何东西。
AFAIK F#不缺少.NET / COM互操作的“必备”。在F#中,您可以执行诸如out和byref参数,声明字符串文字以及支持将属性放在几乎所有内容之类的内容。
答案 1 :(得分:6)
F#中的命令式编程比人们会让你相信要好得多。 F#的match statement太棒了。为什么其他语言没有实现它我不知道。就语法(mutable,ref等)而言,它们很容易使用。你会被F#的稀疏性所破坏,当语法大于正常时,很容易抱怨。 Tuples也很棒。它们也将在C#4.0中。 Currying是Imperative的另一个奖励。
关于面向对象,我发现我很少在纯F#项目中使用继承,而是喜欢使用组合和接口。这主要是因为使用primary contructor允许您将其参数用作方法中的私有属性(不确定我是否正确说明)。其他语言结构(如模式匹配)也会使您远离继承。我没有做任何混合项目C#/ F#所以我不能对此发表评论。
F#并非都是玫瑰。
我对F#和游戏编程的最大问题是性能。在F#中实现的速度非常快,而且我经常在我想到它的同时获得原型并运行我想要做的事情然而我发现自己为了性能原因而不是在C#中重写代码。
问题的部分原因是我对函数式编程风格缺乏经验,即使用Seq,List,Map及其所有附带的方法,如map,iter,fold,scan。我的第一个功能解决方案几乎从来不是最快的,而我的第一个程序解决方案几乎总是接近最好的。我想说这部分不是我。在某些情况下,函数式编程不会使其自身具有性能。
我现在在F#中使用的功能数据类型比我开始使用时少。
修改强>
自从发布此消息以来,已经过去了好几个月,而且我不再遇到性能方面的问题。我的第一个功能解决方案现在通常更简单,几乎是最优的,并且不可变的数据结构很简单。我现在唯一的性能问题是CLI,如果需要,我总是可以做c ++ / cli。我现在使用除了接口之外的一些继承,但它仅用于匿名对象。
答案 2 :(得分:5)
关于OO的东西,我的清单可能是
也就是说,F#在OO部门也有优势,比如类型推断,本地功能,简洁的语法......所以总的来说,我可以把它称为“重度OO”部门。
(我几乎没有做任何类型的UI编程,所以我没有资格在那里权衡。)
(编辑:我也想插入那个,即使你明确选择从问题中排除'工具',我认为工具有点重要,在这方面其他托管的VS语言也很出色。)
答案 3 :(得分:1)
我对静态类型函数式语言的最大痛苦是无法在需要推断的方法上使用变量参数。喜欢地图功能。在F#中你需要map2 map3等。
另一方面,C#也没有这个,除非你想通过反思。
以Scheme为例,这不是静态类型的。定义可以处理map_1 ... map_n的所有情况的单个函数没有问题。当然你放松了静态类型的安全性,但与编写简洁代码的额外方便性相比,它显得相形见绌。
答案 4 :(得分:0)
仅供记录:F#有堆栈分配 - 尝试无限递归,这不是尾递归,你会得到堆栈溢出。除了你知道你可以安全地使用尾递归F#(在C#中它取决于它)之外,它与C#中的堆栈分配没有什么不同。
另外,我要指出的是,当你遇到非常繁重的面向事件的代码时,F#在允许你构建一个框架来执行调度事件到处理程序等的“管道”方面比C#更好。管道成为你的大部分代码。对于简单的UI,C#或VB可能适合更多人。对于复杂的情况,F#领先,我个人需要帮助解决复杂的情况而不是简单的情况。