我听到很多关于函数式语言的知识,以及它们如何很好地扩展,因为函数周围没有状态;因此,该功能可以大规模并行化。
然而,这对我来说没什么意义,因为几乎所有真实世界的实用程序都需要/有状态来照顾。我还发现有趣的是,大多数主要的扩展库,即MapReduce,通常都是用C或C ++等命令式语言编写的。
我想听听功能训练营的消息,我听到这种炒作来自......
答案 0 :(得分:13)
添加一个词很重要:“没有共享状态”。
任何有意义的程序(使用任何语言)都会改变世界的状态。但是(某些)功能语言使得无法同时从多个线程访问相同的资源。缺少共享状态会使多线程安全。
答案 1 :(得分:7)
Haskell,Scheme等功能语言具有所谓的“纯函数”。纯函数是一种没有副作用的函数。它不会修改程序中的任何其他状态。这是线程安全的定义。
当然,您可以用命令式语言编写纯函数。您还可以找到Python,Ruby甚至C#等多范式语言,您可以在其中执行命令式编程,函数式编程或两者兼而有之。
但Haskell(等)的观点是你不能写一个非纯函数。嗯,这不是严格正确的,但大多数情况下都是如此。
类似地,许多命令式语言具有不可变对象的原因大致相同。不可变对象是一旦创建状态就不会改变的对象。根据定义,不可变对象也是线程安全的。
答案 2 :(得分:6)
你在谈论两件不同的事情而没有意识到。
是的,大多数真实世界的程序都有某个地方,但是如果你想进行多线程处理,那个状态不应该无处不在,事实上,地方越少它在,越好。在功能程序中,默认情况下不具有状态,您可以准确地将状态引入您需要的位置,而不是其他地方。处理状态的那些部分不会像多线程那样容易,但由于程序的所有其余部分都没有副作用,因此执行这些部分的顺序无关紧要,这消除了并行化的巨大障碍
答案 3 :(得分:4)
你会感到惊讶!是的,所有程序都需要一些状态(特别是I / O),但通常你不需要更多。仅仅因为大多数程序都有大量的状态并不意味着他们需要它。然而,这对我来说没什么意义,因为几乎所有的现实世界 实际课程需要/有状态照顾。
使用函数式语言进行编程可以鼓励您使用较少的状态,从而使您的程序更容易并行化。
许多函数式语言都是“不纯的”,这意味着它们允许某些状态。 Haskell没有,但是Haskell有monad,它基本上可以让你从零开始获得一些东西:你使用无状态结构获得状态。 Monads使用起来有点繁琐,这就是为什么Haskell强烈鼓励你将状态限制在尽可能小的程序中。
我也发现大多数主要的扩展库都很有趣,即 MapReduce通常用命令式语言编写,如C或C ++。
在C / C ++中编程并发应用程序是“难”的。这就是为什么最好在库中进行经过严格测试和检查的所有危险物品。但是你仍然可以获得C / C ++的灵活性和性能。
答案 4 :(得分:2)
高阶函数。考虑一个简单的简化操作,对数组的元素求和。在命令式语言中,程序员通常会自己编写一个循环并一次执行一个元素的减少。
但是这个代码制作多线程并不容易。当你编写一个循环时,你假设一个操作顺序,你必须说明如何从一个元素到另一个元素。你真的只想说“对数组求和”并使用编译器,运行时或其他任何东西,决定如何处理数组,在多个内核之间根据需要划分任务,并将这些结果组合在一起。因此,不是编写一个循环,而是在其中嵌入一些附加代码,另一种方法是将表示“添加”的内容传递给可以执行divvying的函数。一旦你这样做,你就会在功能上写作。你将一个函数(加法)传递给另一个函数(reducer)。如果以这种方式编写,那么它不仅会使代码更具可读性,而且当您更改体系结构或想要为异构体系结构编写时,您不必更改夏天,只需更改reducer。在实践中,您可能有许多不同的算法,它们共享一个减速器,因此这是一个很大的收益。
这只是一个简单的例子。您可能希望以此为基础。在2D数组上应用其他函数的函数,将函数应用于树结构的函数,组合函数以应用函数的函数(例如,如果您具有上面的树和下面的数组的层次结构),等等。