一篇有关函数式编程的形象生动教程

栏目: 编程语言 · 发布时间: 5年前

内容简介:函数式编程(FP)与面向对象编程(OOP)的诞生的时间差不多,但它最近才最受欢迎,特别是在JavaScript社区中,为什么?我在00年代早期就学麻省理工学院。计算机程序的体系结构和解释(SICP)是我的教科书。所以我的第一个正式学习的编程语言是函数性的,然后我在工业界工作了十多年,几乎没有多少时间考虑过使用FP。当得知大学的教科书被认为是“函数性编程圣经”时很震惊。别误会我的意思,这是一本很好的教科书。我敢肯定它会让我成为一个更好的程序员,但这并不是我需要经常在Java / ActionScript /

函数式编程(FP)与面向对象编程(OOP)的诞生的时间差不多,但它最近才最受欢迎,特别是在JavaScript社区中,为什么?

我在00年代早期就学麻省理工学院。计算机程序的体系结构和解释(SICP)是我的教科书。所以我的第一个正式学习的编程语言是函数性的,然后我在工业界工作了十多年,几乎没有多少时间考虑过使用FP。当得知大学的教科书被认为是“函数性编程圣经”时很震惊。

别误会我的意思,这是一本很好的教科书。我敢肯定它会让我成为一个更好的程序员,但这并不是我需要经常在Java / ActionScript / PHP / Python / Ruby / JavaScript等职业生涯中使用的东西。

然后我在Wyncode Academy任教四年,并发现自己试图向新手解释FP概念。这很难 - 比OOP更难。

为什么FP比OOP更难?

相关问题:为什么FP需要这么长时间才能流行起来?

我们编码社区需要解决为什么FP难以教授。像一个宗教说教一样传播FP重复了同样的错误,导致FP长期在这个行业中萎靡不振。

对FP的许多介绍都遗漏了一些东西。它不仅仅是一种替代编程风格。这是一种新的思维方式,它代表的类似的技巧也可以与来自OOP背景的更有经验的 程序员 一起使用。

我在Wyncode中使用的技术之一就是讲述一个难以理解的概念时,首先让学生了解概念的背景以及 这个概念的大致样子(big picture),之后就更容易解释技术细节了。

大致样子(big picture):历史背景

计算机是如何工作的?最常见的(流行的?易于理解的?)计算模型是图灵机。FP程序员抱怨的状态正在图灵机中正视着我们。用于操作该机器的算法表示不同状态之间的转换,例如从打开 / 关闭 (1或0)的一些盒子到打开 / 关闭的一些其他盒子。

如果我们试图想象两个图灵机同时在同一磁带上运行,我们就可以开始理解为什么“共享状态”和OOP中的并发性都是难题。

图灵机是一台通用机器。它可用于解决每个可有效计算的数学和逻辑问题。这是个简单的操作集: 向左移动,向右移动,写点,读点,擦除点(增删改查CRUD)。 足以(给予足够的时间和资源)来解决宇宙中的每个数学问题。

这就是艾伦·图灵在1936年所证明的。

在许多方面,图灵机是计算机“工作”的方式。但这也是计算机的工作原理。但是还有另外一种理论:

电路是不同的计算模型。每个逻辑门(AND,OR,NAND,NOR,XOR等)都是纯函数。他们接受输入并产生没有副作用的输出。如果我们只有能够创建和组合这些“函数”,我们还可以解决宇宙中每个可解决的数学问题。这也是阿隆佐·邱奇在1936年证明的。

所以我们有两种不同的计算模型:图灵机​​的0和1(对象)和阿隆佐·邱奇用逻辑门(函数)构建的lambda演算。哪一个是正确的?

有一段时间,关于抽象图灵机是否能解决与lambda演算相同的数学问题(反之亦然)的辩论。最终他们被证明是等同的。

等同意味着它们同样强大。任何可以为图灵机编写的算法也可以使用函数编写。因此,任何可以用图灵机软件编写的程序也可以用电路硬件表示。

“硬件编程”是什么意思?我们可以看到 专用集成电路(ASIC)中 体现的“硬件编程” 。可以创建“编程”的电路,以便快速完成一件事,比如 我的比特币下棋

我们现在有两种编程选择。硬件更快,软件更慢。在软件中犯了错误?只需点击删除键,然后重试。硬件出错?是时候抓烙铁了。这是一个经典的工程设计权衡。

因此,假设我们有一个以OOP风格编写的算法,我们希望将其转换为ASIC硬件编程。以FP风格重写程序可能是一个很好的策略,因此它可以更好地映射到底层电路图。

面向FP的语言往往看起来像电路。特别是Unix,Elixir,F#,JavaScript和其他“管道操作员” 使代码看起来像电路图:输入进入左侧,流过许多“门”(管道)直到它们被转换进入右边的最终输出。某些语言(|>)使用的管道运算符看起来像逻辑门,这可能不是巧合。

大致样子(big picture):哲学

我拿到了我的CS学位的哲学辅修,所以我着迷的一件事是这两个研究领域的交集。我发现在教授新程序员时,特别是那些具有人文学科而不是STEM背景的程序员,有助于在这两个领域重叠处讨论思想。

FP中一个哲学上重要的概念是“函数相等 functionally equivalent”。

也许证明这种等价性的最好例子是 汤姆斯图尔特的 伟大文章 “从无开始编程” 。这里借用他对数字如何完全用函数表示的方式来解释编码:

首先将数字0的概念定义为接受函数参数但不对其执行任何操作的函数。

# Ruby
ZERO = -> (func) { 
  # does nothing
  func
}

类似地,我们可以将所有自然数定义为接受函数参数的函数,并将它们调用n次。

ONE = -> (func) {
  # calls it once
  # same as func.call()
  func[];
  func
}

TWO = -> (func) {
  # calls it twice
  func[]
  func[]
  func
}

要测试这些“函数数字”,请将它们传递给测试函数。

HELLO = ->() { puts <font>"hello"</font><font> }

# same as: ZERO.call(HELLO)
ZERO[HELLO] # nothing displayed
ONE[HELLO]  # one </font><font>"hello"</font><font> displayed
TWO[HELLO]  # </font><font>"hello"</font><font> twice
</font>

这种函数数字符号表示法其实很难玩和调试。因此,为了更容易使用,我们可以定义一个函数,将这些函数数转换为我们习惯使用的对象数字。

# convert number function into number object
def to_integer(func)
  # count how many times counter is called
  n = 0
  counter = ->() { n += 1 }
  func[counter]
  n
end

p to_integer(ZERO) # 0
p to_integer(ONE)  # 1
p to_integer(TWO)  # 2

这个转换器创建计数功能并将其传递给数字函数。ZERO函数将调用它为零次,ONE函数将调用它一次,等等。我们跟踪计数器被调用多少次以获得结果。

对于这些函数数字定义,我们可以实现添加各种功能:ADD SUM统计等。

ADD = -> (func1, func2) {
  -> (f) { func1[func2[f]] }
}

sum = ADD[ZERO, ZERO]
p to_integer(sum) # 0

sum = ADD[ZERO, ONE]
p to_integer(sum) # 1

sum = ADD[ONE, ONE]
p to_integer(sum) # 2

如果TWO调用一个函数两次,那么ADD[TWO, TWO]将返回一个调用其参数四次的函数数字(函数数字FOUR)。

这是一个令人费解的方式。当我看完“从无开始编程”这本书时,我感觉这是一个巧妙应用基本计算机科学概念的有趣书籍,但不是我在日常工作中可以使用的东西。

而这正是我(我怀疑很多其他人)对FP一般的感觉 - 它很聪明,但似乎没有用。这是我们需要解决的问题。

所以,教FP更好的开始地方是“黑客帝国3:矩阵革命”。

什么是矩阵与FP呢? 这部电影告诉我们:我们没有证据证明我们周围的世界是真实的。也许世界上有实际的物体,或者我们只是 在罐子里的大脑

因此,至少有两个相互矛盾的理论,例如,第一个是什么。我们可以与之交互(触摸和感觉)是一种(名词,对象)吗?或者它是一个动作(一个动词,一个函数),一个作用于世界的东西,但没有实在的呈现?

函数数字one是数字1的模拟,它是在函数等同 functionally equivalent于对象数字one,意味着它可以做对象数字one做的任何事情。

但是OOP中的对象“存在”并不是真的“存在”。这是一个矩阵模拟。它没有固有属性 - 它不是x,它只是像x。

打个比喻,你坐在真正的椅子上只是一种 用力按压你的身体 功能?“椅子”可以是存在于现实世界中的椅子这个对象,也可以是一种椅子功能:一种希望用舒适的力量推动你的功能,并没有潜在的客观基础。

想想颜色,红色美味的苹果真的是红色的(形容词、描述名词)还是扮演红色(动词)?颜色是真正的底层苹果对象的固有属性,还是仅仅是当光照在它上面时执行函数的动作结果呢?苹果真的还是模拟的呢?

解释这个哲学概念的难度是解释为什么FP难以教授的好隐喻。为了帮助学生理解,首先要开放他们的想法,让世界完全由“功能/函数”组成。从样子big picture概念开始,然后转向世界的FP模型:它们与OOP表示的区别以及它们如何具有相同的结果。(banq注:从概念开始转向有两个:一个是名词,一个是动词,FP是转向到动词,而我们日常是转向名词,但是很多人没有意识到这种转向,所以很难转到动词方向去接受函数编程)


以上所述就是小编给大家介绍的《一篇有关函数式编程的形象生动教程》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

运营前线 2

运营前线 2

兰军 等著 / 机械工业出版社 / 2017-4 / 69.00

“运营前线”是一个系列,目前已经出版2部,与“产品前线”一样,该系列书也由资深的产品和运营专家兰军(Blues)领衔策划和写作,旨在梳理和总结国内一线互联网公司的运营方法和技巧,让所有产品人和运营人都有机会了解和学习这些大的互联网公司是如何做运营的。 这2部作品汇集了来自腾讯、阿里、百度、360、迅雷、YY、小米、爱奇艺、乐视等数十家大型互联网公司的一线运营专家的技巧和方法论。共包含9大运营......一起来看看 《运营前线 2》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具