“ PLO将不再能够将我们从Cloud Monsters中拯救出来。”
译者注: 有两个概念-并行性(同时执行,独立执行)和竞争性(依次执行,但同时执行多项任务),而且,一如既往,我不得不选择正确的术语来砸头。
我将在原文中的括号中复制一些单词或术语,以便寻找英文术语的更多信息,这些信息的数量会增加很多倍。也许您已经听说过这样的表达,例如:“ Clojure”,“ Scala”,“ Erlang”,甚至“ Java现在有lambdas”。尽管有一个遥远的关于``函数式编程''的想法,但您已经有了。如果您是任何类型的编程社区的成员,那么您可能已经讨论了该主题。如果您在Google上搜索“功能编程”一词,则不会看到任何新内容。较早创建的语言中的第二种语言已经涵盖了该主题;它是50年代创建的,称为Lisp。那么,这到底是什么话题呢?仅仅60年后?起初,计算机非常慢
信不信由你,计算机比DOM最慢。不完全是。同时,在协议中关于编程语言的设计和实现有两个主要思想:计算机没有足够的计算能力来处理所有抽象和处理以功能样式编写的程序。因此Lisp之前已经筋疲力尽,因为它非常缓慢,因此不适合工作。从那时起,命令式编程风格的统治就开始了,尤其是在C的鼎盛时期。但是计算机已经有了很大的进步。
现在,使用大多数应用程序几乎已经成为一种正常现象,而完全不在乎它们所用的语言。功能语言终于有了第二次机会。功能编程50.5
本文决不是FI的介绍。在本节的最后,您将需要了解什么是AF,以及如何开始学习之旅。您可以从字面上理解术语“函数式编程”,就像使用函数进行编程一样,这并非事实。您将根据其他功能创建功能并编写功能(您还记得学校课程中的功能吗?现在将派上用场)。就是这样FP功能列表(不完整):- 一流的功能
- 高阶函数
- 纯函数
- 关闭
- 不变的状态
现在,您不必担心这些奇怪的术语,只需了解它们的含义即可。一流的函数意味着您可以将函数保存在变量中。我确定您做了类似的事情,例如JavaScript示例:var add = function(a, b){
return a + b
}
您刚刚创建了一个匿名函数,该函数获取a和b并返回a + b,并将该函数分配给add变量。高阶函数意味着函数可以返回函数或接受函数作为参数。再次在JavaScript中:document.querySelector('#button')
.addEventListener('click', function(){
alert('yay, i got clicked')
})
要么var add = function(a){
return function(b){
return a + b
}
}
var add2 = add(2)
add2(3)
这两个选项都是高阶函数的一个示例,即使您没有编写这样的内容,也可能在其他地方看到了类似的内容。纯函数意味着函数不会更改变量,它只是接受数据并返回数据,就像我们在数学中喜欢的函数一样。这也意味着,如果使用参数2调用函数f并返回10,则它将始终返回10。无论什么环境,线程数或执行顺序都没有关系。它们不会在程序的其他部分引起任何副作用,这是一个非常强大的概念。短路意味着您可以在函数内部保存一些数据,这些数据将在特定的返回函数中可用,换句话说,返回函数存储其运行时。var add = function(a){
return function(b){
return a + b
}
}
var add2 = add(2)
add2(3)
再次查看段落高阶函数中的第二个示例,变量a已关闭,仅在返回的函数中可用。实际上,闭包不是FP范式的功能,而是优化。不可变状态意味着您根本无法更改任何状态(尽管可以创建新状态)。在以下代码中(在OCaml上),将变量x设置为5,并且x始终为5。let x = 5;;
x = 6;;
print_int x;;
这些功能看起来很奇怪,但是您很快就会看到它们如何使您的生活更轻松。面向对象的编程不再保护您
这是一个充满希望的时机,我们终于可以拥有分布式和多线程应用程序了。不幸的是,尽管我们现有的(或使用最多的)模型可以解决当前的问题,但还没有为并发和并行做好准备,但同时也增加了很多问题。为了改善应用程序,我们需要一种简单可靠的方法来实现我们想要的。您还记得AF的上述功能吗?纯功能和不变状态?没错,您可以在不同的内核或机器上执行数千次功能,结果将始终相同。因此,我们可以在相同的内核和数千个内核上运行相同的代码。生活再次变得万里无云。“但是为什么我不能继续使用OOP?”
至少对于多线程和并行性,OOP不再能为您提供帮助。因为OOP指的是具有可变状态的状态(在大多数情况下以命令式语言编写的命令式语言)。对象的调用方法应该更改当前的self或this。您将必须付出足够的努力来正确更新和同步所有线程。我写这篇文章的目的并不是要激怒您从当前使用的范式切换到FP(尽管有些人会说我应该这样做),但是您应该绝对理解:Java和C ++ 11已经具有lambda演算。我可以说几乎所有现代和受支持的语言都将实现FP功能或已经实现了FP功能。值得注意的是,我们不应该停止使用可变状态。我们必须使用输入/输出(IO)等,以便我们的程序有用。FP的主要思想是:仅在确实需要时才使用可变状态。“我不使用云,我真的需要学习自动对焦吗?”
是。函数式编程将帮助您更好地编写程序并讨论您必须解决的问题。“我努力了。太复杂了,很难阅读代码。”
在任何领域,启动总是很困难。我敢肯定,即使是使用OOP语言,您也开始学习编程也有很多问题。也许开始以OOP风格编写代码比编写第一个程序要容易,因为您已经熟悉一些常见的习惯用法,例如声明变量和for / while循环。开始学习FP几乎与重新开始从头开始编写程序一样(无论您开始学习哪种语言,从一开始都是毫无疑问的)。许多人可能会注意到,AF难以阅读。如果您有使用命令性语言的经验,则功能程序将看起来像密码术。并不是因为它确实如此,而是因为您不知道它的主要成语。一旦了解了基本原理,程序将变得更加可读。查看用Haskell和JavaScript(命令式)编写的程序:guess :: Int -> [Char]
guess 7 = "Much 7 very wow."
guess x = "Ooops, try again."
function guess(x){
if(x == 7){
return "Much 7 very wow."
}
else {
return "Oops, try again."
}
}
这是一个非常简单的程序。当用户猜到并输入数字7时,它将显示一个祝贺消息,或者在所有其他情况下显示一条错误消息。也许这看起来像加密,因为Haskell只需两行代码即可完成所有工作(您可以忽略第一行,这只是一个“类型声明”)。但是一旦了解了模式匹配的可能性(不仅在FP语言中实现,而且在它们的功能中实现),它将变得非常简单。Haskell的操作:如果接受的猜测参数是7,那么它将返回“非常好哇7”。或返回“糟糕,再试一次”。在其他情况下。这与JavaScript代码是一样的,但是Haskell映射到程序员在代码中声明的“模式”。如果可以使用if / else,这种方法在这种情况下似乎不太有用。但是,当您自己开始编写更复杂的数据结构时,它将变得非常有用。plus1 :: [Int] -> [Int]
plus1 [] = []
plus1 (x:xs) = x + 1 : plus1 xs
在上面的程序中,* plus1 *是一个函数,它接收一个整数列表并将该列表的每个元素加1。该函数比较列表何时为空[](返回另一个空列表,因为其中没有元素)绕过非空列表并确定匹配的模式:x为列表的第一个元素,xs为其余列表。然后,它简单地计算总和并通过递归调用将其合并。我相信您会花很多时间(不是最愉快的),以命令式的方式重写此示例,将代码分成两行,同时保持可读性。所以我们开始吧
关于函数式编程的许多材料已经出版,但是您不应该明确地跳过这些链接:- Scala中的函数式编程原理:本课程对于那些了解Java并想尝试函数式编程而又无需退出JVM的人很有用。本课程涵盖基本概念。
- 计算机编程范例-基础知识:本课程对那些想学习如何用功能语言编写程序的人很有用。该课程使用Qz学习语言。本课程中有很多练习,您可以使用功能语言并尝试创建自己的数据结构。我相信该课程为称为``功能编程''的``构建''提供了构建基块,它将在将来帮助您使用其他语言。
不幸的是,这些课程仅在年底提供。但是您可以关注内容和视频,它们可在Youtube上获得。另一方面,如果您更喜欢文字材料,我当然会推荐其中一些:- 计算机程序的结构和解释
- 如何设计程序
- 计算机程序设计的概念,技术和模型
前两个课程具有相似的课程,向您介绍函数式编程的基础,并且非常适合初学者。该链接中的第三个链接是“计算机编程范例”课程,不仅仅涉及函数式编程。重要的是要注意这些材料是入门级的。此外,克里斯·艾伦(Chris Allen)写了一篇有关函数式编程研究的出色文章。它被称为功能教育。并提供了详尽的材料清单,供您使用Haskell研究函数式编程,并讨论了这种方法的优缺点。通过Chris推荐的链接,您可以学习函数式编程的基本原理和更复杂的主题(我肯定您听说过monad),也许您会了解如何使用它们编写应用程序。(感谢克里斯提供的材料链接。)祝您新年快乐!☺