对象函数式编程 Scala简史

本文概述了Scala语言诞生过程当中的各类软件开发运动历史的事件,当人们研究Scala时,发现这是一种给人印象深入的语言,可是因为这种语言的功能特征不断的急速进化,致使除了一些本身研究的项目外,没有其余人再使用这种语言开发了。java

从前,有一种编程语言叫Scala,人们研究这种语言,发现这是一种给人印象深入的语言,有人说与Scala接触的最大感觉就是Java如影相随。这种语言看起来很美,但没有人愿意冒险把本身的职业生涯依赖于这种语言上,这个语言太年轻了,谁能保证它不会夭折?程序员

以后,发生了一些事情; Scala 长大了。 Twitter 宣布他们用Scala语言替换了之前一些用Ruby开发的后端程序,而SAP也在使用这种语言,还有EDF等。 这消息迅速传播开来,有许多新的程序开发者慕名而来,他们也都感受到这是一种使人印象深入的语言,同时,早期的这个语言的信徒也开始发现此语言已经凤凰涅磐,让他们眼睛一亮。web

他们如今看到的这种语言已是一个成熟的、急不可待的等人们使用它去大展宏图的语言了。 随着2.8版本的发布,Scala 终于从少年进入了青年,能够当之无愧的接受使人印象深入的赞誉了。编程

编程就是人生后端

程序语言在进化、在繁衍,产生不一样的种族。很是相似于生命在早期地球的上的构成,编程语言最初是诞生于由CPU指令和数学概念混成的沸腾的高汤里。 跟生命的发展不一样的是,它们不须要泥土,可是它们也经历着残酷血腥的优胜劣汰、物竞天择过程,固然,你能够把它们之间的战争想像成关于Tab键和Space键,关于括弧在程序中的地位问题上的战争 。设计模式

人们就像一个优秀的饲养员只喜欢挑选一个纯种血统的良马同样选择本身喜好的编程语言。 就像生物学上,人工育种必然存在不足,近亲接二连三地繁殖、以此来保存某一血统的使人满意的特性的作法必然潜藏基因缺陷的危险。数组

父母的结合产生的后代汇聚了其父母双方各自不一样的特征,因此后代比前代更强大,同时父母各自的弱点也会被后代查明从而摒弃。 一样的思想也被应用到了编程语言的世界里,各类面向对象和面向函数风格的概念相互融合给予了程序员们史无前例的能力和表达方式,Scala编程语言就是这样的语言中的一员。服务器

我估计阅读我这篇文章的大部分是Java程序员,因此在我详细的解释函数和对象如何交互以前我打算先介绍一些关于针对函数编程的概念。其实在网上已经有了不少彻底超出个人写做水平的好教材,因此我愿意尽可能简单的介绍一下。闭包

什么是函数?架构

数学里,函数就是接受一个值(输入值)然后使用它产生另一个值(输出)的运算。 在很长的时间里这个定义几乎适用有全部任何的状况,即便是如今,数学家们也只是在扩充这个定义里的值的概念:复杂数值,矩阵,向量,坐标(对称坐标和笛卡尔坐标),四元数。.. 不少东西均可以被看成值,只要你用正确的方式去看待它。

这种状况持续了好久,以后程序员出现了,以后计算机被发明了。
一旦人们对计算机技术的重要性达成共识,而且使计算机技术逐步完善起来,程序员就开始用一种新的思想考虑他们了,好比:看着这计算机打印输出的长河般一排排的三个字母组成的汇编程序码,你不头痛也不行。

若是他们能把那些序列码按相同的功能分红一组一组,给它们起个名称,那么他们将会有一种简洁的方式去重复利用这些代码,那么之前花大量时间拼写这些代码的时间节省下来,终于有了去酒馆的时间。 由于不少的程序员也都是数学家,由于不少他们的程序都是用来解决数学问题的,这就决定了函数的概念很是简洁的迎合了这种给编程单元打包处理的行为,今后第二代编程语言诞生了。

完美中的不足

这种革新,完美中有些不足。 针对函数,人们发现一个问题,就是常常须要它们一次处理多个输入值,或,更使人沮丧的,多个输出值。 幸运的是一些数学家解决了若是让函数处理多个输入值的问题,这种思想很早就被人采纳了,人们按照这种思路想出来如何去返回多个输出值(一般是把输入值给抹去,替换我想要输出的值)。 可是其余的一些数学家(例如Haskell)并不喜欢多个输入值的方式,他产生了一个新的观点,用高阶函数替代多个输入值,函数能够返回其它函数,或能够用函数体看成函数参数,但这种作法很难实现,因此程序员起初都没在乎这种观点。

函数编程还有一个问题,就是它有反作用。 一个函数使用一个相同输入值(例如读一个文件)却能够每次都作出不一样的事情,或者它能够去作一些不专注的事情(例如处理返回一个值外还会向控制台打印一行字)。 更糟糕的是,它会把本身的输入值在使用以后改变其值! 对于那些想利用这些反作用的人来讲,这是再好不过了,但是对于另外的一些数学家就不同了,他们不喜欢喝啤酒,但是还必需要把啤酒杯拿在手上。

因此程序里的函数跟数学里的函数是不一样的。 人们给出了一个新的定义(不是很精确的):一个程序,或者一批指令,具备一个名称,能够选择性的拥有一个或多个输入值和输出值,甚至同时具有多个输入值和多个输出值,同时还能作点额外的事情。

A reprive ahead of its time

天然,不少数学家并不高兴函数被定义成这样,因而一个新的语言品种被创造了出来,用来弥补其先天的不足,再一次的将它用一个稳固的理论架构肯定下来。函数体成为第一类实体,而非之前的仅是一批代码的别名。 这样Haskell的高阶函数的概念就能够应用于设计开发软件了。 编程语言的进化发展中人们愈来愈多的鼓励使用常量值,这样函数就不能把输入值给能脏了。 人们实现了局部套用(Currying),开始使用数组结构,这样函数终于又回到了只能接受一个输入值和一个输出值的绅士面貌。 一些有趣的方法被人们采用来限制那些讨厌的反作用:若是这些反作用不能彻底避免的话,那就把它们规整起来专门找个地方放置它们。 这样的语系被人们称做为函数式编程语言,由于它们把函数的概念回归到了其数学上的根源。 这个语系里的语言包括有Lisp, Scheme, Caml, Erlang, F#, Clojure等。

做为工程学上一个优秀的典范,函数式语言具备设计优良,易理解,高效,结构稳定等优势。 与此同时,如同其余Good Ideas?常常遇到的状况同样,很长的一段时间里它们被主流团体所遗忘。 程序员们都很清楚为何人们喜欢把函数放在首要位置; 人们须要把系统按单元功能划分,相互不依赖,能够在不一样的地方重复使用它们。 这些愿望就像痒痒须要挠的感受折磨着人们,因而面向对象的思惟今后诞生了并崛起了。

目前,函数式编程只是被人们当成一种业余爱好,也被人们用在相关的演讲和论文里去灵巧的阐述一些新事物。 人们一般认为函数式语言会比命令式语言运行的慢,但这种结论也许只有上帝知道,由于历来没有人用本身的方式证实过。 人们还认为,尽管函数式语言看起来很是简洁,适合小的程序和作演示用,但它们不太适合大规模的程序,像那些成百上千行的程序,若是用函数式语言来开发,几乎是不可维护的。

重生

实际上,函数式语言并不仅是一种玩物。 跟随着时代革新的大潮,它在地下酝酿了这么多年,终于等到了这个世界但是接受它的这一天。 主流程序员们愈来愈多的认识到,函数式语言是如此的容易使用,而这一点在其它(面向对象)代码是难以达到的。 就好比这个简单的问题处理这个字符串队列,将它们所有转化成大写后返回,用Java编写却有可能出错。 由于偶尔人们会忽略掉这个队列里的第一个字串,由于他们从1开始计数,而不是0。有时候人们会发现这个队列里的字串不是按他们要求的部分转化成大写,而是所有大写了,还有些时候程序会报出空指针异常。

逐渐的,人们开始讨论起closures和continuations,为的是让他们的程序更加的强壮和可维护。 当时这些东西并非对象们所能具备的,因而增强型for循环被发明了,还有匿名类,visitor模式,command 模式。 固然这些没有一个能按照程序员们想象的那样的完美,但这些东西仍是有用的,让不少有问题的地方变得可维护了(即便这样须要编排一些丑陋的模板式的代码)。 时机已经到了人们改变思惟方式的时候了,函数式语言已经火烧眉毛的看到本身的宏大入场了。

让人嫉妒的特性

经过Erlang语言,爱立信演示了函数式语言如何能应用于大规模系统的。 而其开发效率高,可维护性,可测试性都很好,特别是不易犯错。 这才是真正的函数式语言的面貌,感受比面向对象语言要成功的多。 爱立信的程序员们史无前例的有了充分的喝啤酒的空闲时间了。 生活变得轻松起来!

而在另外的阵营里的程序员看待函数式语言有点想法,也有的嫉妒。 Java变得如此臃肿,并且,每个新出现的特征都看起来是围绕着它的模板代码风格创造出来的。 即便是很小的程序,如今也要使用annotations,模板参数,和duplicate type declarations,大程序问题就更大了。 不幸中的不幸,关于如何往Java里添加closures(闭包)功能的讨论并不像早期预期的那样顺利,还有,Java bean里的数不完的get/set方法实在是不能在忍受了。
有些事情必需要变了。

除了这些,Java还有一大堆的问题。 The Virtual Machine(虚拟机)是一个很是成熟的工具,通过了很好的优化,市场上随处可见,从洗衣机,移动电话,到数不清的web服务器和桌面电脑里都有它的身影。 Java系统在开源库和框架方面已经发展的使人瞠目结舌繁华,在一些付费系统里也火的不得了。 靠着Java这棵大树,市面上已经处处都是由各类企业投资推进的数不清的团队开发工做创造出的成功和成熟的java项目,若是由于一些小的语言特征而放弃Java这一切基本是不可能的。

咱们一块儿作蛋糕 也一块儿吃

咱们全部作的事既要继承Java全部目前的优质资产,同时也要使用函数式语言从新描绘新的编程语言版图,Scala正好迎合了这种须要,尽管它有不少的竞争对手。 Pizza语言第一个出现的,但它跟今天的Scala比较起来更Scala当初的形式。

咱们所知的能在JVM上跑的语言大概有JavaFX, JRuby, Jython, Groovy 等。 大部分都有closures 和其余的一些函数式语言具备的特征,但在Java王国里,这些新生事物并非那么的血统纯正,它们的特征更像是外来移民,护照很新亮,但有异域口音。

动态语言的流行是无济于事的; 类型能够经过各类方法隐藏起来,让人感到它的不存在,可是这样很难编译出原生的Java代码了。 这是个很大的问题,特别是你写出的对象须要拿到第三方类库里去处理时。 有时候各类语言之间很难交互,一般须要一个解释器,就像JSR233 Scripting API 或 the Bean Scripting Framework 那样。Scala却有与生俱来的优点,它和Java的结合是如此的紧密,它能像本身自己的类型那样处理Java类型,它并不像一个外来移民,而是一个侨胞,并且是有护照的公民。

你从外面看,Java和Scala编译出来的代码是如出一辙的,没有区别,这有点让人难以置信,但能够明确的告诉你们,Scala最初就是这样设计出来的。 当你把Scala看成一种函数式语言时,你会更惊奇的发现,它把面向对象和函数式的两种风格以其优雅的方式彻底融合统一块儿来。

正由于它和Java是如此紧密的联系,你能够把Scala看成Java临时的替代品,它绝对不会强制你用任何的函数式风格的代码书写。 它的类型引用,简洁的属性存取,以及带有成员变量参数的构造函数,你几乎能够把它看成一种风格简洁的Java。 除了上述的优势外,咱们能够称赞Scala为某些方便比Java面向对象更成功的语言:

一切皆为对象,包括数值和函数

在Java中,方法不是对象,更别提基本数据类型了。 2.toString在Scala里是一个合法的语句。它抛弃了静态类成员,Java的这个问题能够追溯到它所效仿的C++上,是个历史错误。 C++自己就是个混合型的语言,它的设计目标就是要兼容过程式的C语言,同时也要支持对象结构。 静态成员不是彻底的可面向对象,由于他们不能实现接口,以及向普通成员那样的多形性和覆盖、过载。 当你把一个对象看成参数传入一个函数时,静态成员是不可用的。

相反,Scala提供了singleton objects, 这样这种问题就不存在了。 Scala里新的companion概念可让你使用singleton去访问具备相同类名的实例上的一个有约束限定的成员,这样你就能够把静态成员的权限复制出来。

类上全部的属性都实现了behind-the-scenes,就像是个隐藏域,并且有针对它的一对Get和Set隐藏方法。 那些任何人均可以直接修改的内部属性将再也不被容许公共访问,在未来,虚拟类的概念将会在Scala里出现,那样后Scala对对象的支持将会有更惊人的表现。函数式编程对下面的特征进行了支持:

◆对递归函数的尾调用(tail-call)优化

◆模式匹配

◆第一类函数和高级函数

◆局部函数(能够接受任何输入值)

◆局部套用(Currying)和函数局部应用

◆闭包

◆简洁的声明常量值的语法定义,很好的支持常量集合的类库

◆continuations (scala 2.8 新增)

全部的这些都意味着什么?

函数式编程已经证明了它的实力,快速增加的开发者人数是最好的证实,Scala向你们演示了如何在不牺牲面向对象思惟模式下接受函数式设计模式的概念。 它同时也向你们显示了若是将这两种风格的语言如何融合到一块儿变成一个强壮丰满的新语言,不带任何的形式的勉强。

一旦你了解了基本语法并对闭包、第一类属性、高阶函数、traits,、immutable refs等概念有了认识,它的各类特色的相互结合会向你展现它更深层次的潜质。 语言生命里的一些设计思想的选择和肯定最终致使了一个增效做用,咱们认定这种新一代的对象-函数式的设计正是使Scala今天如此成功的关键。

相关文章
相关标签/搜索