F#的缺点是什么?

10

直接的C#/Java代码非常难以并行化、多线程等。因此,直接的C#/Java代码将使用越来越少的处理能力(因为现在所有的东西都会是多核心)。

解决这个问题在C#和Java中并不简单。可变性和副作用对于在C#和Java中完成任务至关重要,但这正是使多核心、多线程编程如此困难的原因。

因此,函数式编程将变得越来越重要。

考虑到J2EE/Ruby世界将在众多的功能性/多核心方法中分化(就像它对几乎所有其他事情所做的那样),而.NET的人们将全部使用F#,这种想法表明F#将在两年后变得非常流行。

这种思路的问题在哪里?为什么不明显F#将会非常流行?

(编辑) Larry O'Brien在这篇博客文章中精辟地阐述了这一点:“我认为,在语言方面,这是一组锻炼的练习,在其中C和C ++表现出色-至少到多线程部分。具有列表处理惯用语的语言最初也会做得很好,但可能会存在内存消耗问题(特别是函数式语言)。最终,我认为,托管C衍生语言(Java和C#)在达到锻炼9的过程中有最简单的路线,然后面临着锻炼10的严重不足,其中并发问题起主要作用。我认为,并发将成为未来五年职业发展的核心问题,因此这些不足非常重要。”


11
如果你必须问为什么,那么很明显这不是显而易见的。 - Otávio Décio
2
@ocdecio说:“为什么人们不明白F#将会变得非常重要?”这意味着:“为什么不是每个人都明白F#将会变得非常重要?”显然,这并不明显。我想知道为什么不明显。 - user128807
4
你觉得 F# 会变得非常流行,为什么?为什么特别选择 F#?它并不是一个完美的多线程语言。毕竟它仍然严重依赖于标准的命令式语言 .NET 库。它也不是一个无副作用的语言。假设人们会因为并行化机会而盲目地转向函数式语言,你认为为什么 F# 会成为“那个”语言? - jalf
1
下一个问题是并行化Java和C#存在多少问题与语言本身的设施有关,以及多少困难实际上与并行编程本身的困难有关。如果函数式语言普遍更擅长并行编程,那就是一回事。如果它们只是为另一组问题交换解决方案,那就是另一回事了。 - David Thornley
1
@unknown - 这篇博客文章忘记了一件事,那就是 F# 处理几乎所有 C# 处理的任务同样容易。所以,最坏的情况下,如果你需要完成特定任务,F# 和 C# 一样繁琐 -- 而且,通过类型推断,通常还更容易。C# 更好的几个案例是某些特定的互操作场景和 OO 中的一些东西,比如隐式接口。 - MichaelGG
显示剩余5条评论
12个回答

11
直白的C#/Java代码非常难以并行化,但如果使用Task Parallel Library则不是这样。F#能否成为主流取决于成本效益是否存在,这一点并不明显。如果.NET开发人员发现他们可以使用函数式方法编写某些类型的程序,比使用命令式方法快三分之一(我认为在某些类型的程序中可能是真的),则应该有一些采用F#的动力。Paul Graham在创业公司中使用Lisp的经历说明了这个过程。Lisp为他们提供了巨大的竞争优势,但Lisp并没有占领世界,不是因为它不强大,而是因为其他原因,比如缺乏库支持。由于F#可以访问.NET框架,因此具备一定的竞争力。参考:http://www.paulgraham.com/avg.html

是的,但你看,TPL和我见过的其他C#/Java解决方案一样,需要开发人员(或多或少地)显式地并行化代码。这非常难做到,因为它要求开发人员深入了解硬件的运作情况。这与函数式编程形成鲜明对比,其中开发人员可以免费获得多线程支持。 - user128807
要有效地使用并行fx库,您只需要知道如何编写良好的for循环。您可能想查看有关该库的30分钟播客http://channel9.msdn.com/shows/Going+Deep/Programming-in-the-Age-of-Concurrency-Anders-Hejlsberg-and-Joe-Duffy-Concurrent-Programming-with/。 - Robert Harvey
此外,并行fx库和F#的内部存在一定的重叠:请参见http://channel8.msdn.com/Posts/401/。 - Robert Harvey
我不认为TPL需要太多关于硬件/操作系统的知识,因为TPL将并行化抽象到更高的层次:任务(工作单元)而不是线程。你从不涉及线程,只涉及任务。如果你可以将想要完成的工作分成多个块,那就完成了。 - JulianR
@user128807:自动并行化仍然处于非常实验性的阶段,即使对于哈斯克尔语言这样切割边缘的函数式编程研究也是如此。 - Mauricio Scheffer

9

函数式编程比命令式编程更难理解。F#在许多方面比C#更难学习。大部分“开发者”不理解函数式编程概念,甚至不能写出很好的C#命令式代码。那么他们写好F#函数式代码的希望又在哪里呢?

而且,考虑到团队中每个人都需要理解、编写、调试、修复等使用你选择的语言编写的代码,这意味着你需要一个非常强大的团队--不仅仅是一个非常强大的人--才能够像使用它应该被使用的那样使用F#。而这样的团队并不多见。

再加上现在有8年的C#/VB代码存在,这些代码不太可能被迁移掉,而且在C#/VB中创建类似BCL的库更容易,因为在公共接口中泄漏元组等内容不易,所以我认为F#将难以获得更多的用户,只会被强大的团队用于新的内部项目。


1
但是当C#/Java开发人员在机器上使用10%的处理能力时,F#程序员使用80%时,C#/Java开发人员该怎么办?C#/Java开发人员如何证明自己的存在? - user128807
14
这个行业存在多年,很多所谓的开发人员几乎不知道他们在干什么(可以查看thedailywtf.com)。中高级经理们大多对这些问题毫无头绪,仍然雇佣烂开发人员生产出烂代码。它只在10%的硬件上运行可能是最不值得担心的事情之一。 - Greg Beech
3
即使使用像F#这样的函数式编程语言,许多东西也不容易并行化,而有些东西根本就不需要并行化。 - Robert Harvey
1
是的,不幸的是,F# 的语法不够像 C 语言,所以它不会流行起来 : )。但我是认真的——尽管 F# 的核心语言比 C# 简单得多,但对于太多人来说,这是太大的变化。即使 C++ 添加了 lambda 支持,这种情况可能仍然存在。因此,互操作性和……可用性(这是一个不冒犯的说法吗?)……将是 F# 没有流行起来的主要原因。 - MichaelGG
1
函数式编程可能比命令式编程更难学,但比现代面向对象编程容易多了。 - J D
显示剩余4条评论

6
  1. 在SO上提出一个编程问题,并指明你正在使用F#。
  2. 提出同样的问题,并指明你正在使用C#。
  3. 比较答案。

使用一种新的编程语言是一种经过计算的风险——你可能会得到更多内置功能和语法糖,但你将失去社区支持、雇佣程序员的能力以及解决语言盲点的能力。

我并不是在挑剔F#——每个编程语言的决定都是需要进行风险计算的。如果人们没有在C#上冒这个险,我们现在仍然会使用VB6和C++。对于那些语言与它们的前辈相比也是如此。你必须为你的项目决定优势是否超过了风险。


6
两年后,这个真的适得其反了。F#在stackoverflow上的问题拥有一些最佳答案,大多数情况下甚至是由微软F#团队成员这些真正的专家或常规语言用户回答的。 - Mauricio Scheffer

3
  • 命令式代码比函数式代码更易于编写(至少,可以更容易地找到可以编写可接受的命令式代码的人而不是函数式代码)。
  • 有些东西本质上是单线程的(用户界面 *是最著名的例子)。
  • 已经存在很多C#/C/C++代码,并且在同一个项目中使用多种语言会使该项目的管理变得更加困难。

就个人而言,我认为函数式语言将越来越普及(甚至F#本身就是这一点的证明),但可能永远无法像C/C++/Java/C#等语言那样获得广泛的应用。


*这显然是一个有争议的观点,所以我会详细说明。

在多线程UI中,每个UI事件都以异步方式分派并在自己的线程上运行(实际的线程管理可能比仅仅启动新线程更复杂,但这与讨论无关)。

请想象一下,如果您正在渲染窗口,则应该执行以下操作。

  • 窗口管理器要求您绘制每个元素(对于每个元素,可以期望收到一条消息或一个函数调用)。
  • 每个元素读取其状态(隐含地读取应用程序状态)。
  • 每个元素绘制自己。

在步骤2中,每个元素必须锁定应用程序状态(或影响显示的子集)。否则,在更新应用程序状态的情况下,渲染窗口的最终结果可能包括反映两种不同应用程序状态的元素。

这是一次锁定协会。每个渲染线程将锁定、渲染,然后释放; 因此它们将串行执行。

现在,想象一下您正在处理用户输入。首先,由于用户非常缓慢,因此除非您在UI线程上进行了大量工作,否则无法获得任何好处;因此,我假设就是这种情况。

  • 窗口管理器将用户输入通知您的应用程序(再次,消息、函数调用等)。
  • 从应用程序状态中读取所需内容。(这里需要锁定)
  • 花费时间来计算一些数字。
  • 更新应用程序状态。 (这里也需要锁定)

您所做的一切都只是从显式地启动工作线程到隐式地这样做;代价是如果您对锁定状态不够严格,那么可能会出现heisenbugs和死锁。

UI api的根本问题在于您正在处理一种多对一(或一对多,这取决于您如何看待它)的关系。无论是多个窗口、多个元素还是多个“输入类型”,都会影响单个窗口/表面。某种形式的同步必须发生,当它发生时,多线程就没有任何好处而只有缺点。


4
UI之所以“本质上是单线程的”,是因为Microsoft的实现赋予了所有线程亲和力。 - jalf
请列举一个非单线程的UI框架。线程亲和性只会导致“快速失败”的行为,在使用Swing/AWT多年后,当我转到.NET领域时,这种行为是非常受欢迎的。 - Kevin Montrose
2
微软设计他们的用户界面为单线程是有充分的理由的 - 在一个用户可能同时进行许多操作的环境中,多线程很容易使得即使是最简单的用户界面也会变成并发噩梦! - Justin
1
@Kevin 用户输入并不是改变UI的唯一理由。这是我所知道的最大好处。通过并行UI框架,你可以在理论上同时处理多个UI元素,而不是按顺序进行。想象一下,如果你能将UI渲染分离到多个核心中,Windows加载/卸载/响应速度会快多少。有很多好处。 - Joseph
1
有没有研究表明函数式编程风格相对命令式编程风格更难掌握?如何消除许多人从C、Java或类似语言开始的偏见?当然,在你迫使自己思考如何推动比特位之后,这样做可能会很困难,但我不认为这应该是一般情况下更容易的方式。 - MichaelGG
显示剩余11条评论

3
目前没有任何反对 F# 的案例,但您必须了解我们作为开发人员所处的情况背景。
多核架构仍处于初始阶段。将单线程应用程序改变为并行架构的主要推动力需要时间。
F# 有很多用途,其中之一是并行性,但不是唯一的用途。函数式编程在科学研究中也非常有用。这将在许多领域产生巨大影响。
然而,您提出问题的方式听起来像是在暗示 F# 已经在打败仗,这绝对不是事实。我已经与许多科学家交谈过,他们正在使用类似 MatLab 等软件,而且很多人已经意识到 F#,并对它感到兴奋。

1
没错。我和所有转向F#的项目交流过的人都对它持积极态度。我还没有听说过有人学习了F#,然后又回到C#这样的语言。 - MichaelGG

3
这种想法有什么问题?为什么不明显F#会变得非常流行呢?
你假设大众实际上编写需要多核支持的程序,或者这些程序从并行化中获得了显著的好处。这是一个错误的假设。
在服务器端,甚至更少需要使用并行语言。 后端服务器处理通过其本质的并发性(工作通过线程和进程在客户端之间分配,例如一个应用服务器,一个数据库服务器,一个Web容器..)已经充分利用了多核/处理器的支持。

2
我认为这是一个关键问题。许多程序已经足够快了,使它们更快(除了从更快的单核心获得的加速)的好处很小,这是不是事实?很好地表征哪些程序集将受益于加速,哪些程序集将不会受益,这将是很好的。您关于服务器端并行化的评论没有区分粗粒度和细粒度并行性。许多服务器端应用程序将受益于多线程。例如,我熟悉的所有交易处理内容都受益于并行化。 - user128807

3
这种推理的问题在于假设一切都会按计划进行。同时,还有假设F#比C#更容易编写多线程程序。虽然通常情况下,函数式语言比命令式语言更容易实现多线程,但历史上功能性语言在流行度上并不占优势,因此找到熟练使用命令式语言的开发人员更容易。这两个因素取决于人和应用程序,可能会达到平衡点。总的来说,在功能性或命令式语言中编写多线程应用程序是否更容易还为时过早。此外,还有一个假设,即人们将要求充分利用其1K核心计算机,但大多数应用程序并没有受到CPU计算能力瓶颈的限制,而是受本地I/O、网络和用户延迟影响。未来巨型多核处理器是否是未来潮流也尚不确定,可能市场较小,芯片制造商会生产更小的芯片而非更强大的芯片,或者将资源投入我们目前尚不清楚的其他事物。此外,还有一个假设是F#将成为功能性语言中的佼佼者。作为VS 2010的功能性语言,它确实具有相当的优势。但竞争还没有真正开始,事情还有很多变数。F#.NET是否是编写大规模并行PC的特别好的语言尚不确定,未来可能会出现其他更好的替代品。此外,到便宜笔记本电脑上常见64核处理器的时候,微软和.NET是否真的那么重要也还不确定。总的来说,这一系列假设结合了合理的原因而非严格的逻辑,并试图以明年的事情为基础预测未来。这种方式极为不可靠。

在倒数第二段中列出的假设中,我唯一关心的是“F#在多线程方面将比C#好得多”。当然,我与所有我交谈过的C#开发人员都说,微软将为他们提供解决问题的解决方案。然而,我发现这很难相信,因为C#中的所有内容都是可变的并具有副作用,但我可能只是不知道这个领域的最新方法。 - user128807
C#似乎不是特别有前途的多线程语言,但我无法立即判断F#会好多少。拥有超过四个内核的CPU尚未得到普遍使用,并且我们没有编写大规模多核用户软件的经验。 - David Thornley

3
如果有人反对它(如果真的存在这样的情况),那就是大多数现代专业开发人员使用不同的工具(以及不同类型的工具)。F#为这个领域带来了一些独特的工具,那些拥抱它们的人将会发现自己的专业才能在其他编程任务中非常有用,尤其是那些涉及大数据集分析和操作的任务。
我所见过的F#真的让我惊叹。每次演示都让我面露微笑,因为F#给我留下的印象是一个高级版的函数式编程,在“好旧时光”中我记得函数式编程更加普遍(可能更“旧”而不是“好”,但这就是怀旧情结)。

2

我不同意C#很难并行化的前提。如果你知道该怎么做,它其实并不难。此外,Parallel Linq会让这变得更加容易。我是否希望C#有一个OpenMP?当然,但是如果你足够好的话,C#提供的工具可以让你几乎做任何想做的事情(而且我觉得现在甚至不需要那么厉害了)。


我认为Java也是如此。Azul公司非常重视Java,并且他们的业务建立在在许多(数百个)内核上提供性能的基础上。我的客户通常在一些32个内核上运行他们的Java应用程序,它们也可以很好地扩展。即使我们为他们提供的工具令人自豪,但在Java或C#中将应用程序扩展到多个内核并不是什么高深技术。 - Fredrik

2

关于技术,有几个值得注意的事情:

  • 最好的技术解决方案并不总是最受欢迎或最常用的。(而我不知道 F# 是否好用)我认为 SQL 是雇主们最常使用、最需要的编程语言,但在我的书中它并不是一种好的、酷炫的、快速的、友好的、有趣的语言。如果最好的技术解决方案总是“胜出”,那么如何解释 QWERTY 键盘?如果你曾经阅读过 x86/x64 处理器的“设计”,就会明白了 ;)
  • 只使用 Java 的 Azul 公司拥有 864 核心服务器,并且未来趋势是更大的服务器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接