Scala:Java+函数式=后函数式?

原创
开发 后端
在面向对象仍占据主流的今天,可能很对程序员还没有接触过其实相当古老的函数式编程;但函数式在多核时代来临之际正愈发显得重要。函数式编程相关的讨论中经常涉及到Scala这个JVM之上的语言,而其创始人对其的定位是:后函数式语言。

【51CTO精选译文】之前的一段时间,Scala社区掀起了一阵讨论,主要观点包括“Scala不是一个函数式语言”以及“Scala不够函数式”,并把Scala与F#Erlang等“纯粹的”函数式语言放在一起进行对比以证明(51CTO编辑注:函数式语言以其并行编程的优势正逐步扩大自己在多核时代的影响力,而上述的三个语言都是相关讨论涉及的焦点)。有观于此,Scala创始人Martin Odersky于前日在Scala官方网站上更新了一篇文章,称Scala是一门“后函数式语言”。虽然Martin提出的是一个新概念,但文章对于函数式语言的特点进行了非常全面而简短的总结,如果你对函数式语言到底如何强大并不十分了解,那么这篇文章是很好的学习材料。以下是全文——

Scala 是否是一门函数式语言?过去几年,我们长时间地对这个问题进行了讨论。一方面,Scala 在本质上提供给了那些常常与函数式编程关联在一起的编程结构,而且大量的 Scala 代码是纯函数式的。另一方面,有相当多的人并不认同 Scala 为函数式语言这一说法。

相关阅读:

  1. Scala讲座:函数式语言的体验
  2. Scala简介:面向对象和函数式编程的组合
  3. Scala如何改变了我的编程风格:从命令式到函数式

我认为用来描述 Scala 的一个非常不错的形容词是:后函数式 (postfunctional)。函数式编程所有必要的组成部分都被 Scala 吸收了,即使某些“看起来的感觉”是不同的。此外,函数式编程只是 Scala 这个更大的工具箱中的一部分,也是非常重要的部分。函数式编程正在逐渐主流语言吸收,对于这个大趋势,我认为 Scala 是其中的一个领先者。这种变化正来势汹汹。例如,C# 的每个新版都要比之前的版本更具函数式(虽然根据51CTO之前文章的介绍,C#的尝试似乎不太成功),甚至 Java 最终也会拥有闭包(closure)。当然,增加闭包或类型推理并不能成为一门函数式语言,但这个趋势是有目共睹的。

对于 Scala 是后函数式语言的观点,我应首先澄清在我看来什么是函数式语言。对于函数式语言这种说法,基本上包含两个定义,一个是狭隘的定义,一个是宽泛的定义。狭隘的定义认为函数式编程语言应仅认可纯函数,而且不可具有副作用。根据这种定义,几乎没有一门函数式语言还在使用中:即使 Haskell 也具有 I/O 单子(monad)和 unsafePerformIO。因此我更喜欢那个宽泛的定义:函数式语言让以函数为中心的编程变得容易和自然。我认为这正是 Scala 所具有的特性,所以这个就是它应被视为函数式语言的原因。

为了挖掘更多详细的细节,下面我们做一个功能列表,这些功能通常是与函数式语言相关联的。

◆作为第一类(first class)值的函数:具有

◆方便的闭包句法:具有

列表解析(list comprehension):具有。 Scala 的表达式可以表示列表以及其他单子。

柯里化(curry)函数定义和应用:具有。lazy val 以及 lazy stream 的形式。

模式匹配:具有

Tailcall 优化:半具有。Scala 自动优化直接循环 tailcall。对于其他调用,存在显式的 tailcall 方法,使用 trampolining 技术。

将焦点进一步缩小到静态类型函数式语言,还有几点:

强大的泛型,包括较高类别的类型:具有

类型类:具有,通过隐式参数进行模块化。

类型推理:半具有。Scala 具有局部类型推理,很有用;但相对于 Haskell、ML 和 OCaml 语言中所用的 Hindeley/Milner 类型的推理,功能没有那么强大。不过从另一方面来看,局部类型推理对于子类型化更好。

人们是否像使用函数式语言那样使用 Scala?当然是的。比如,Scala 编译器资源和 Scala 库主要是用函数式风格编写的。Map、filter、fold 无处不在。模式匹配也是处处使用。非常少的可变变量,并且其中多数用于单赋值形式。

为什么有人不同意 Scala 是函数式语言的说法?看起来存在两个主要原因:句法选择和面向对象语言的角色

Scala 感觉更少是函数式语言,因为其核心句法大部分是继承了 Java 的传统,而不是 Lisp、ML 或 Haskell。这三个编程语言是函数式语言家族里最重要的先行者。

尤其特别之处在于,Scala 不具有一个不同的、通常比较笨拙的句法,用于用印(dereference)可变变量以及用于定义有效计算。你也许会认为这是不好的,因为它还不足够打消程序员继续他们命令式编程的老习惯。这是一种裁决:你想要用一门语言来获得什么。这种判断是完全必要的。不过在这篇文章中,我感兴趣的只是描述 Scala 是什么,而不是为什么 Scala 会是这样,或者它是否应该是其他模样。

此外,Scala 也没有某些被视为典型函数式语言的句法。比如,相对于其他函数式语言,curry化更为冗长,在 Scala 使用更少。还有,它没有代数数据类型,你必须编写一系列 case 类作为替换。

Scala 不被视为函数式语言,某些时候还有其他原因,因为它接受了面向对象而不是拒绝它。某些使用函数式编程的人误解了面向对象语言,认为面向对象语言天生与可变状态相关联(平心而论,其实是许多关于面向对象语言的出版物加强了这种观点)。Scala 建立在这样一个前提之上:一门语言既可以是函数式的也可以是面向对象的,并且两者的结合让人获益良多。

总之,如果你看看 Scala 提供的功能,它基本上是一门函数式语言,但从表面上它不总是像一门函数式语言,而且它不会强迫你去采用函数式编程风格。对于它的许多用户,函数式编程构造是 Scala 中最主要的工具,但并不是唯一的工具。事实上,在 Scala 的设计中,函数式构造、命令式构造花费了大量的心血,并且所有对象都能够在一起很好地运行。我认为对于这种混合“后函数”一词是非常恰当的。

#t#一个有趣的对比对象是结构化编程。在七十年代,结构化编程曾是最主要的新编程风格,诸如 Pascal、Modula 和 Ada 被创造出来,它们比其他语言更好地迎合了这种风格。二十年后,你还会问 Java 是否属于结构化编程语言吗?既然看起来不同,它从本质上包含了那些较早的语言的所有功能。而且它还没有 goto 语句,这让 Java 成为了结构化语言?也许吧。事实上所有这些都不再重要。结构化编程已经成功达到了一个层次:几乎所有语言现在都遵循它制定的原则,既然表面的句法不同。而且,对于今天的编程语言,结构化控制只是很多风格中的一种而已。

我希望函数式语言将会走上同样的道路:它被主流语言吸收,直到人们不再认为函数式编程是一种不同的、新颖的、外来的代码编写方式,并且在每天的如此工作中使用它。相同的事情已经发生在之前的结构化编程和面向对象编程身上。函数式编程很可能就是下一个,因此 Scala 将是后函数式语言飘来的第一缕新风。

责任编辑:yangsai 来源: 51CTO.com
相关推荐

2010-03-11 10:34:22

Scala

2009-12-11 10:44:00

Scala讲座函数 scala

2009-07-21 17:16:34

Scala函数式指令式

2009-09-27 15:23:00

Scala讲座函数式编程Scala

2009-07-08 16:10:24

Scala简介面向对象函数式

2009-09-27 15:29:00

Scala讲座面向对象Scala

2016-10-11 13:32:50

函数式TypeScriptJavascript

2009-06-09 13:18:56

Scala函数式命令式

2019-09-09 11:40:18

编程函数开发

2020-09-23 07:50:45

Java函数式编程

2020-09-22 11:00:11

Java技术开发

2013-09-09 09:41:34

2016-09-30 09:43:17

JavascriptTypeScript函数式编程

2017-06-08 14:25:46

Kotlin函数

2009-07-09 00:25:00

Scala函数式

2010-07-07 13:11:20

ScalaF#C#

2010-07-09 14:12:00

ScalaF#C#

2012-03-14 10:09:51

ibmdw

2024-02-28 08:37:28

Lambda表达式Java函数式接口

2022-07-07 09:03:36

Python返回函数匿名函数
点赞
收藏

51CTO技术栈公众号