何时使用功能性编程语言?


90

在哪种情况下,我应该选择使用功能性编程语言,而不是使用更冗长的面向对象语言(例如C ++,C#或Java)?

我了解什么是函数编程,而我真正不了解的是针对什么类型的问题,这是一个完美的解决方案吗?



2
总是。或至少永远不会。
谢尔比·摩尔三世

1
对于lambda,C#具有边界功能。
JD 2012年

Answers:


50

在我看来,功能语言主要有两点好处:游戏AI和数学计算。由于其良好的列表操作(至少在Lisp和Scheme中),因此在游戏AI中是好的,并且由于其语法而在数学计算中也是如此。Scheme,Lisp和Haskell的语法使数学计算易于阅读。我要补充的最后一件事是功能语言是非常有趣的语言。我的计划课程是我最喜欢的课程之一。


2
在解决了我的大脑在编译器课程的第一周就想爆炸的事实之后,我参加了Scheme,我也发现它很有趣(而且我对此做得更好)
Alex Baranosky

1
您使用了哪些功能语言进行数学计算?
Jules

8
还有,编译器!我听过用Haskell编写过编译器的人说,他们“不会再用命令式语言编写过编译器”。
ShreevatsaR

1
julesjacobs:我同时使用了haskell和Scheme来解决简单的数学计算。我对这些语言一点都不擅长,所以我有办法解决更复杂的问题。我现在不能使它们足够快。
martiert,2009年

95

我本人对此进行了一些研究,并认为我可以在使用功能性语言的原因列表中增加共识性。看到在不久的将来,使用相同的cpu技术将无法提高处理器速度。该架构的物理原理是不允许的。

这就是并发处理进入的地方。

不幸的是,由于数据之间的相互依赖性,大多数OOP语言不能一次利用多个处理器。

在纯函数式编程语言中,计算机可以一次运行两个(或更多)功能,因为这些功能不会改变外部状态信息。

这是您可能喜欢的有关函数式编程的出色文章


38
我不会说大多数OO语言都不能利用任意数量的处理器。我要说的是,一个程序要以有效和可靠的方式同时利用许多处理器,就必须对程序进行组织,以使大多数计算密集型代码单元的行为都像纯函数一样。可以用大多数语言以这种方式组织程序。使用功能性语言比使用命令式(包括面向对象)语言更容易。
扎克2010年

2
感谢您链接该文章。它确实帮助我解释了一些事情。
guptron 2014年

13

我的一个朋友引用他的一位大学教授的话说:

在顶部绘制一个网格,其数据类型在左侧,而对这些数据类型的操作则在左侧。如果垂直分割网格,则表示正在执行OO;否则,请执行以下步骤。如果将网格水平切片,则说明您正在执行FP。

我的回答是,FP是一种完全可行的编程方法,具有与OO一样广泛的应用程序。与任何编程语言选择讨论一样,我认为更重要的问题是:

  1. 您是否有时间投资学习新的符号和新的思维方式?
  2. 您正在考虑使用哪种语言具有足够丰富的库,以至于您不会因重新发明轮子而陷入困境?

关于第一个问题,如果您这样做主要是为了学习价值,我建议您看一下Haskell,因为支持材料范围很广(书籍,文章,活跃社区等)。

关于第二个问题,Haskell具有不错的库范围(尽管有些库比其他库更成熟),但是Scala(在JVM上运行的混合OO功能语言)具有的优点是您可以逐渐过渡到功能样式,并且您可以使用各种Java可访问的库。


我是在大学期间学习Scheme的,所以我不想只是为了体验而学习函数式编程。出于实际原因,我宁愿学习一些功能性语言。
亚历克斯·巴拉诺斯基

9

实际上,您在PP中可以做的所有事情都可以在FP中完成,反之亦然。这只是编写某些内容的另一种方法-对该问题的另一种观点以及解决问题的另一种方法。

但是,由于使用FP的人并不多,问题更多的是缺少良好的库,可移植性/可维护性(因为维护人员比Scheme拥有更好的机会来理解用C ++编写的内容),以及缺少文档和社区。我知道有一些文档,但是,将其与C ++,C#或Java进行比较,您会理解我的意思。

但是,如果您确实想执行FP,则即使在C ++和C#中也可以使用此样式。当然,如果您使用标准库,它将不是100%FP。不幸的是,我认为C#没有针对与函数式编程一起使用而进行过优化,它可能会带来很多性能问题。

我对FP的看法比较主观。这不是一个严格的声明。


8
“几乎所有你能在PP做可以FP做” -其实,这是确切的一切。
BlueRaja-Danny Pflughoeft,2010年

2
@BlueRaja-您是指图灵完整性吗?如果是这样,您说的话就不会遵循。例如,Conway的《人生游戏》是Turing Complete,但是您不能像在C中那样使用它编写视频卡驱动程序。同样,我也看不到Haskell编写的任何最新游戏。可以在FP中完成!=理论上可以在理论FP中完成。
路易吉·普林格

@Luigi Plinge我必须同意BlueRaja。Haskellers讨论了一些用Haskell编写的Linux驱动程序。 我没有链接,但我也听说过用Haskell(可能还有其他功能语言)编写了一个操作系统。就游戏而言,我看不到用C#或Java编写的最新游戏,是否意味着它们不能用于此类游戏? 无论如何,以FP编写游戏的示例。另外,请记住,我的大多数链接都是Haskell,这是一种纯函数式语言。
austinprete 2011年

@PardonMyRhetoric显然,您可以在Haskell中编写游戏并进行任何计算,但是速度会慢几倍,并且内存使用会更高。因此,与BlueRaja的陈述相反的例子是,您不能在FP中编写“一款速度快且使用C语言占用大量内存的游戏”。这是一个实际的实际问题,而不是一个花哨的技巧(而且我根本不打算抨击FP-我现在正在编写Scala!)。
Luigi Plinge 2011年

1
@PardonMyRhetoric它也需要是惯用的FP。您看到的使Haskell性能接近C的基准是以大多数Haskell程序员无法编写的“低级”单项风格编写的。例如,您可以通过简单地输出Haskell代码并编译C代码来达到类似的性能。毫无意义。一个相关的实际问题是“您可以做什么”与“可以/可以完成”之间的关系。如果某件事太难了,那么从理论上讲是可能的(并为谁“可能”?)并没有多大关系。
路易吉·普林格2011年

4

函数式语言在很多情况下都是很好的。它取决于特定功能语言的库。

您将如何回答“何时使用面向对象的编程语言?”这一问题?


1
“何时使用面向对象的编程语言?” 另一方面,当您想对任何事物进行建模时,我一直在寻找一个问题,那就是fp是直观的解决方案,我仍然在寻找,这就是我找到这篇文章的方式。
jimjim

@Arjang我猜想函数式编程将在只需要输入即可生成输出的计算应用程序中找到巨大的用途。没有可变性,没有迭代
EdgeDev

3

尽管这是一个主观的问题,但我想补充一点,功能语言经常用于解析领域特定的语言;功能性质非常适合语法分析。


2
解析DSL?我认为使用Lisp宏等,DSL被实现宏,而不是Lisp程序可以解析的东西。具有非Lisp语言的YMMV。:-P
克里斯·杰斯特·杨

1

从我所看到的,更多的是品味而不是功能(不是双关语)。确实没有任何一种语言风格可以使它在特定任务上固有地变好或变差。


2
@JonHarrop-想要详细说明吗?我觉得它并不那么明显,如果您留下您只是在贬低boostererisim投票给人们的印象,那将是可耻的。
TED

1
ML系列语言专门用于元编程,另外还添加了复杂的语言功能,例如用于处理树(例如,表达式树)的模式匹配。因此,这种语言家族在本质上比该特定任务好得多。
JD 2013年

1
@JonHarrop-我会接受的。但是,您是在谈论ML,而不是一般的功能语言。我是DSL的忠实拥护者,因此我坚决反对使用特定语言来完成其特定的任务。
TED

如今,几乎在所有功能语言中都可以找到模式匹配,包括OCaml,F#,Scala,Haskell,Clojure和Erlang。例如,我最近为专注于数学的客户构建了定制的业务规则引擎。那是F#的1000行,主要是解释器。借助模式匹配,可以轻松完成Lexing,解析,类型检查和解释输入。
JD 2013年

@JonHarrop ..但不是全部。它不是功能语言的固有功能,而这正是问题所在。
TED

1

通常,使用最容易表达问题解决方案的语言。对于函数式编程,这是根据功能轻松表达问题的解决方案的时候(即名称。通常,它对数学运算,AI,模式匹配非常有用;通常,任何可以分解为必须应用以获得答案的规则的事物。在充分分析问题之后,您才能真正确定要使用的“最佳”语言。这是伪代码派上用场的地方。如果您发现自己编写的外观类似于FP的伪代码,请使用FP。

当然,所有完整的编程语言在功能上都是等效的,因此,就可以解决的问题而言,选择哪种语言都没有关系。主要影响将在于编码效率和准确性以及维护的简便性。

还请注意,可以通过巧妙设计的API在OO语言中模拟FP。例如,我已经看到许多Java库(JMock是一个示例),它们使用方法链接来模拟FP DSL。然后,您将看到诸如以下的构造:

logger.expects(once()).method("error") .with( and(stringContains(action),stringContains(cause)) );

本质上,这会构建一个函数,该函数将被评估以确定模拟对象上的某些调用顺序是否正确。(例如从http://www.jmock.org/yoga.html中被盗的示例)

在其他OO语言中,另一个类似于FP的语法是使用闭包,例如在Ruby中。


2
“ ...就可以解决的问题而言,选择哪一个都不重要”。仅当您有无限的时间和金钱来解决您的问题时。
JD
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.