文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

最近我又看到一篇有关如今Scala被IT界采用的博文。文章是Dzone上的“Scala的兴衰” 。 博文中,作者描述了Scala语言没能成为另一大目标程序语言的原因 。但我们能确定Scala的创始人曾假装该语言会被地球上每个开发者使用吗?我不这么认为。

引言

首先,写出这样一篇文章,我是谁啊?基本上我谁也不是。我想做的只是说一说最近5年我使用Scala的体会。我于2013年参加Martin Odersky Coursera的课程,开始学习Scala。我阅读了一些有关Scala编程的书,其中一本是Cay Horstmann所著的 《Scala,献给没有 耐心的人》 (在我看来,这是有关Scala编程语言最好的书籍之一)。最后一点也很重要,从2015年起,我就在大数据项目中担任高级开发员,大量使用了Scala编程语言。

第 1 段(可获 2.2 积分)

后来,去年,我又有过机会了解了Scala的过去,现在和未来。

说这么多-就这么多

你是否从头开始安装过JDK? 肯定装过。你还记得提示至少有30亿台设备运行Java的图片吗?

3 billion devices

这个数量确实很多了,是不是?Java在庞大的Java类库基础上运行了二十年。数百万计的开发者都依赖Java语言创建和维护各种应用程序,以此养家糊口。你真的认为会有新的语言能取代如今的Java吗?

第 2 段(可获 1.38 积分)

我不这么想。但是,也让我们给Scala一个机会。

语言

对于不了解该语言的人来说,Scala是一个令人起敬的编程语言。它便于掌握吗?不,一点儿也不。Scala的语法简洁有力,借鉴了许多老编程语言中的设计,尤其是Java。

例如, class声明与构造函数、属性声明混合。

class Person(val name: String, val surname: String)

上述例子中有很多的概念。以下是相对应的Java class。

第 3 段(可获 1.18 积分)
public class Person {
    private final String name;
    private final String surname;
    public Person(String name, String surname) {
        this.name = name;
        this.surname = surname;
    }
    public String getName() {
        return this.name;
    }
    public String getSurname() {
        return this.surname;
    }
}

如你所见,一行语言在Java中需要写成十多行。一行简单的代码要用一大堆最佳实践和范式来解释,最后成为 不那么自然 的class声明。

再举个例子,让我们来分析一下类的 伴生对象 中的 apply 方法。这是实施 工厂方法 模式的自然方式, 在所有现代接口中被过度滥用。

第 4 段(可获 0.85 积分)
class Person(val name: String, val surname: String) 
object Person {
    def apply(json: String): Person = {
        val name = // Retrieve the name from json string
        val surname = // Retrieve the surname from json string
        new Person(name, surname)
    }
}

上面的例子等同于实现一个通常在Java中调用的静态工厂方法,经常被命名为“of”。 如果你选择使用 Scala 的 case class,伴生对象就自动生成了。

还有很多其他例子证明Scala编程语言包含了许多软件工程最佳实践(有关更多示例,请参阅 A (too) short introduction to Scala )。 仅需要几年的开发经验,您就可以深入理解使Scala语言创始人在设计期间做出决定的过程。

第 5 段(可获 1.19 积分)

我们怎么能假设全世界绝大多数的开发人员可以立即了解Scala语言的微妙特点呢?

函数式编程

多年来,Scala是为数不多的在JVM上运行,混合了函数式编程与面向对象的范例的编程语言。 2015年,java 8中引入了 Lambda 表达式。很多人开始说Scala会死掉,因为Java——我们最喜爱的主流编程语言,也引入了函数式编程。

不幸的是,Java的Lambda表达式本身不足以使Java成为函数式编程语言。事实上,出于很多原因,Java的Lambda表达式仅仅是Java 匿名类 使用的语法糖。

第 6 段(可获 1.39 积分)

你知道么?在Java 5,6,和7中也有函数式代码。

// Define a type for a Function with two parameters
public interface Function<T, U> {
    U apply(T arg);
}

// Implement a specific function
Function<Integer, Integer> square = new Function<Integer, Integer>() {
    @Override
    public Integer apply(Integer arg) {
        return arg * arg;
    }
};

很不舒适,不是么? 为了克服为每种类型的函数定义一个定制类型,而且有一个冗长的语法的问题,在Java 8中,我们添加了一堆*Function类型的API和一个特殊的语法来声明lambda表达式。 然后,在Java 8中代码就变成下面的样子。

第 7 段(可获 0.88 积分)
Function<Integer, Integer> square = x -> x * x;

这就足以说明Java 8是一个函数式变成语言了吗?不幸的是,这还不够。

Java 8缺少了很多“真正的”函数式编程语言的特性。比如说,它的Lambda表达式缺乏封闭变量的能力。事实上,Java 8的Lambda表达式能够访问到外层的定义成final的变量,也就说不可变的变量。Java的Lambda表达式仅针对值封闭。

final Integer three = Integer.valueOf(3);
Function<Integer, Integer> triple = x -> x * three;

这是一个真正的问题吗?一点也不。很多变成语言不建议使用这些类型的闭包(也被称为 full-blown 闭包)。

第 8 段(可获 1.14 积分)

Java 8缺乏的主要特性是,Lambda表达式不是一等公民。Java 8不定义任何 function 类型。Lambda表达式是只有一个方法的接口的实现(如功能性接口/functional interfaces,或SAM,一个仅实现一个抽象方法的类)。这是什么意思呢?

首先,在Java 8中无法声明一个匿名方法的签名。事实上,下面的语句无法编译:

public static void runCalc((BigInteger -> BigInteger) calc) {/* ... */} 

一旦你定义了一个 functional interface,作为 runCalc 方法的参数传进去,我们还是会遇到问题。即使是下面的代码还是不能编译。

第 9 段(可获 1.23 积分)
interface MyCalcLambda {
    BigInteger run(BigInteger input);
} 
public static void runCalc(MyCalcLambda calc) {
    // You cannot use the functional interface as it was a function!
    System.out.println(calc(BigInteger.TEN));
}

克服这个问题的唯一方式,是你直接调用接口中定义的方法。

public static void runCalc(MyCalcLambda calc) {
    System.out.println(calc.run(BigInteger.TEN));
}

另外,Java 8完全不支持模式匹配,如 for-comprehension 语法、ranges 等。这些特性与函数式编程不是密切相关的,他们在这个领域里面可以辅助工作。

第 10 段(可获 0.68 积分)

总之,请不要再说Java 8作为一个函数式变成语言超越了Scala

Scala最佳时间

总之,Java 8和Scala从任何角度都没有可比性。如果Java被定义为一个用于通用目的的编程语言,我们在什么场景下可以有效地使用Scala?

在我看来,Scala的最佳应用是在需要大量数学概念的领域里面。一个明显的例子是大数据领域。Scala架构与大数据代码库(即Apache Spark)中的数据结构很好地匹配。

第 11 段(可获 1.2 积分)

Spark RDD[T]Resilient Distributed Dataset(弹性分布式数据集),像是它顶层抽象的集合。Scala与集合操作相关的特性与这个数据结构能够很好地匹配。

结论

正如我在本文中试图证明的,Scala的目的不是代替Java——现在不是,未来也不是。像现存的其他语言一样,Scala语言有它自己的特性。这些特性结合了很多软件工程的概念。同时,数学在深入理解Scala的过程中扮演了重要角色。这些事实清晰地解释了为什么Scala不会成为一个被广泛采用的语言。

第 12 段(可获 1.28 积分)

然而,这些事实同时说明了Scala可以被成功应用在IT的哪些领域。像大数据或DSL (Domain Specific Language,领域特定语言)领域是Scala最佳的应用环境。

总之,请求大家不要再写表明Scala肯定要死掉的文章或博文。如果你真的这么想,请先只用Java 8写一个Apache Spark的程序。:)

PS:事实上,谈到函数式编程,Scala不是一个 纯粹的 函数式编程语言。一个 纯粹的 函数式编程语言不会允许可变数值:但Scala允许你定义 var 变量。然而,如果你试图编写一个编程语言纯粹度排名,明显Scala要比Java 8纯粹。

PPS:网络社区仍在辩论Java 8的Lambda表达式是不是一等公民。

第 13 段(可获 1.78 积分)

文章评论