Scala (/ˈskɑːlɑː/ SKAH-lah)[1]是一种通用编程语言,它支持函数式编程和强静态类型系统。Scala的设计简洁,[2] 它的许多设计旨在解决对Java的批评。[3]
Scala源代码经编译成Java字节码,以便生成的可执行代码在Java虚拟机上运行。Scala提供与Java的语言互操作性,所以用这两种语言编写的库可以直接被Scala或Java代码引用。[4] 像Java一样,Scala也是面向对象的,并使用大括号语法,这让人联想到C语言。与Java不同,Scala有例如Scheme, Standard ML和Haskell等函数式编程语言的特性,其中包括柯里化,隐含类型,不可变对象,惰性求值和模式匹配。它还具有一个高级类型系统,该系统支持代数数据类型,协方差和方差,高阶类型 (但并不是高级类型),以及匿名类型。Scala中有许多Java所不具有的特性,包括运算符重载,可选参数,命名参数和原始字符串。然而,Scala并没有Java中的检查型异常这一特性,该设计被认为是有争议的。[5]
Scala这个单词是由scalable(可扩展的)和language(语言)组合而成的混成词,这意味着它是随着用户需求的变化而不断发展的语言。[6]
Scala的设计工作是由马丁·奥得斯基于2001年在洛桑联邦理工学院 (EPFL)(瑞士洛桑)开始进行。Scala的设计源自Funnel语言的工作,Funnel是一种结合了函数式编程和佩特里网的编程语言。[7] 奥得斯基曾参与了Java泛型和Sun公司的Java编译器javac的开发研究工作。[7]
在2003年年底发布内部测试后,Scala于2004年初在Java平台公开发布,[8][3][7][9] Scala第二个版本(2.0版)于2006年3月发布。[3]
2011年1月17日,Scala团队获得了来自欧洲研究理事会价值230多万欧元的五年研究资助 。[10] 2011年5月12日,奥得斯基和合作伙伴成立了Typesafe公司(后来更名为Lightbend公司),一家为Scala提供商业支持、培训和服务的公司。Typesafe在2011年从Greylock Partners投资机构获得了300万美元的投资。[11][12][13][14]
Scala在Java平台(Java虚拟机)上运行,并兼容现有的Java 程序。[8] 由于安卓应用程序通常用Java编写,并且在打包时从Java字节码转换为Dalvik字节码(在安装过程中可能被进一步编译成机器码),因此Scala的Java兼容性使其非常适合安卓开发,在函数式开发上尤其是如此。[15]
Scala软件发行版,包括编译器和库,是在Apache许可下发布的。[16]
Scala.js 是一个将Scala程序编译为JavaScript的编译器,它的问世使得可以在web浏览器或Node.js中运行Scala程序。[17] 该编译器自2013年开始开发,并于2015年宣布结束试验阶段(v0.6)。v1.0.0-M1版于2018年6月发布,但在2019年仍是M7版。[18]
Scala Native是一个Scala编译器,它以LLVM编译器基础结构为目标,创建使用轻量级运行环境的可执行代码,并在运行时使用贝姆垃圾收集器。该项目由丹尼斯·沙巴林领导,并于2017年3月14日发布第一个版本,0.1版。Scala Native的开发始于2015年,目标是通过消除代码的初始运行时编译使得它比JVM的即时编译更快,并提供直接调用本机例程的能力。[19][20]
一个针对.NET框架及其通用语言运行平台的参考Scala编译器于2004年6月发布,[7] 但在2012年被正式放弃。[21]
用Scala编写的Hello World程序有以下形式:
object HelloWorld extends App {
println("Hello, World!")
}
不像Java的Hello World程序,Scala中没有类声明,也没有静态声明;而是使用object关键字创建了一个单例对象。
当程序存储在文件HelloWorld.scala中时,用户使用以下命令编译它:
$ scalac HelloWorld.scala
并使用以下命令运行它
$ scala HelloWorld
这一过程类似于编译和运行Java代码的过程。事实上,Scala的编译和执行模型与Java的相同,这使得它与例如Apache Ant等Java构建工具兼容。
“Hello World”Scala程序的一个简短版本是:
println("Hello, World!")
Scala包括了交互式shell和脚本支持。[22] 将以上程序保存在名为HelloWorld2.scala
的文件中,就可以作为脚本运行,无需事先编译,使用命令:
$ scala HelloWorld2.scala
也可以使用选项-e直接将命令输入Scala解释器:
$ scala -e println(“Hello, World!”)”
表达式可以在REPL中以交互方式输入:
$ scala
Welcome to Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_131).
Type in expressions for evaluation. Or try :help.
scala> List(1, 2, 3).map(x => x * x)
res0: List[Int] = List(1, 4, 9)
scala>
以下示例显示了Java和Scala语法之间的差异:
|
|
|
|
这段代码中的一些语法差异是:
Int, Double, Boolean
而不是 int, double, boolean
。def
关键字声明。val
关键字(表示不可变的变量)或var
关键字(表示可变的变量)。return
语句;函数最后执行的语句或表达式的值就是函数的返回值。foo.asInstanceOf[Type]
或特定的函数,例如toDouble
或者toInt
,来转换变量类型,而不是使用Java类型转换运算符(Type) foo
。import foo._
引入包或者库,而不是使用Java的import foo.*;
语句。foo()
也可以直接以foo
语句调用;方法 thread.send(signo)
也可以直接用thread send signo
调用;并且方法 foo.toString()
也可以直接被foo toString
调用。这些语法上的宽松的设计目的是为了支持一些特定领域语言。
其他一些基本的句法差异:
array(i)
调用,而不是 array[i]
。(在Scala内部,前者扩展为array.apply(i)方法,返回引用)List[String]
而不是Java的List<String>
Unit
代替void
类型(见下文)。下面的例子对比了Java和Scala中类的定义。
|
|
上面的代码显示了Java和Scala处理类的一些概念上的差异:
object
关键字,而不是class
。通常将静态变量和静态方法放在单例对象中,其名称与类名相同,后者也被称为伴生对象。[8] (单例对象的基础类名后有一个$
。因此,对于class Foo
伴生对象object Foo
,在底层有一个包含伴随对象的代码的类Foo$
,并使用单例模式。)val
或者var
修饰符声明时,字段也用相同的名称定义,并根据类参数自动初始化。(在底层,对公共字段的外部访问总是通过自动创建的访问方法(getter)和增变(setter)方法。访问方法与字段同名,这就是为什么在上面的示例中显式声明访问方法是没有必要的。)注意,也可以像Java一样声明替代构造函数。将进入默认构造函数(而不是初始化成员变量)的代码直接进入类级别。public
。Scala具有与Java和C#相同的编译模型,即单独编译和动态类加载,以便Scala代码可以调用Java库。
Scala的操作特性与Java的相同。Scala编译器生成的字节代码与Java编译器生成的几乎相同。[8] 事实上,Scala代码可以是反编译为可读的Java代码,但某些构造函数操作除外。对于Java虚拟机 (JVM)、Scala代码和Java代码是无法区分的。唯一的区别是一个额外的运行时库,scala-library.jar
。[23]
与Java相比,Scala增加了大量的特性,并且在表达式和类型的底层模型上有一些根本的差异,这使得该语言理论上更加简洁,并且消除了Java几个极端情况 。从Scala的角度来看,这些特性实际上很重要,因为Scala中的几个新增特性也可以在C#中可用。例子如下:
如上所述,与Java相比,Scala具有很大的语法灵活性。以下是一些例子:
"%d apples".format(num)
和"%d apples" format num
是等效的。事实上,因为函数名被允许由任意符号序列组成(除了一些必须特别处理的圆括号、方括号和大括号例外),像+
和<<
这样的算术运算符就像任何其他方法一样;这种符号命名方法经历的唯一特殊处理涉及优先级的处理。apply
和 update
再句法上有简写形式。foo()
-其中foo
是一个值(单例对象或类实例)—是foo.apply()
的缩写,而foo() = 42
是foo.update(42)
的缩写 。同样地,foo(42)
是foo.apply(42)
的缩写,而foo(4) = 2
是foo.update(4, 2)
的缩写。这用于collection类,并扩展到许多其他的类,例如软件事务内存单元。def foo = 42
)和空参数(def foo() = 42
)方法。当调用空参数方法时,可以省略括号,这在调用不知道这种区别的Java库时很有用,例如,使用 foo.toString
代替foo.toString()
。按照惯例,一个方法在执行时应该用空参数来定义函数副作用。:
)结尾的方法名期望参数在左边,接收器在右边。例如4 :: 2 :: Nil
与Nil.::(2).::(4)
作用相同,前一种形式直观上和输出结果相对应(具有第一元素4和第二元素2的列表)。trait FooLike { var bar: Int }
,实现可以是object Foo extends FooLike { private var x = 0; def bar = x; def bar_=(value: Int) { x = value }} } }
。调用时,仍然能够使用简洁的foo.bar = 42
。breakable { ... if (...) break() ... }
中, breakable
看起来好像是关键字,但实际上只是一种方法的thunk申明。采用thunks的方法或函数通常将它们放在第二个参数列表中,允许括号和花括号的混合使用: Vector.fill(4) { math.random }
与Vector.fill(4)(math.random)
相同 。花括号变量允许表达式跨越多行。map
,flatMap
和filter
。就其本身而言,这些选择看起来可能是有问题的,但总的来说,它们的目的是允许在Scala中定义特定领域语言,而不需要扩展编译器。例如, Erlang向actor发送消息的特殊语法,即actor ! message
可以(并且正在)在Scala库中实现,而不需要语言扩展。
Java对原生类型(例如 int
和 boolean
)和引用类型(任何其他的类)之间有明显的区分。只有引用类型是继承方案的一部分,派生自java.lang.Object
。在Scala中,所有类型都继承自顶级类 Any
,其直系继承是AnyVal
(值类型,例如 Int
和 Boolean
)和AnyRef
(如Java中的引用类)。这意味着在Scala中没有Java中的原生类型和封装类型之间的区别(例如 int
与Integer
的区别);装箱和拆箱对用户来说是完全透明的。Scala 2.10允许用户定义新的值类型。
Scala有for
表达式,而不是Java中的foreach循环遍历迭代器,它类似于Haskell等语言中的列表生成,或者Python中的列表生成和生成器表达式结合。For表达式使用 yield
关键字允许通过迭代现有集合生成新的集合,并返回相同类型的新集合。它们被编译器翻译成一系列对map
,flatMap
和filter
的调用。不使用yield的情况下
,代码将转换为foreach
从而达到对命令式循环的近似。
一个简单的例子是:
val s = for (x <- 1 to 25 if x*x > 50) yield 2*x
运行它的结果是以下向量:
Vector(16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50)
(请注意,表达式 1 to 25
不是特殊语法。to
方法在Scala标准库中被定义为整数类的一个扩展方法,该方法使用一种被称为隐式转换的技术[25],该技术允许向现有类中添加新方法。)
对一个map的迭代更复杂的例子是:
// Given a map specifying Twitter users mentioned in a set of tweets,
// and number of times each user was mentioned, look up the users
// in a map of known politicians, and return a new map giving only the
// Democratic politicians (as objects, rather than strings).
val dem_mentions = for {
(mention, times) <- mentions
account <- accounts.get(mention)
if account.party == "Democratic"
} yield (account, times)
语句(mention, times) <- mentions
是模式匹配的一个例子(见下文)。对map的迭代会返回一组键值元组,模式匹配使得这一元组被分解为键和值的两个相互独立变量这一过程变得非常容易。类似地,列表生成的结果也返回键值元组,因为源对象(来自变量 mentions
)是一个映射,所以这些元组被自动构建到一个映射中。请注意,如果mentions
是持有的是元组的列表、集合、数组或其他集合,上面完全相同的代码将产生相同类型的新集合。
虽然Scala支持Java中所有可用的面向对象特性(事实上,以各种方式对它们进行了扩充),但是Scala还提供了大量通常在函数式编程语言中才能找到的功能。总之,这些特性允许Scala程序以几乎完全函数式的风格编写,也允许函数式编程和面向对象编程混合。
例子有:
一切都是表达式
不同于C语言或Java语言,但类似于诸如Lisp的语言,Scala不区分语句和表达式。事实上,所有语句都是有输出值的表达式。C和Java中,声明返回类型为void
的函数和像while
这样的逻辑上没有返回值的语句,在Scala中被认为是返回一个Unit
类型,这是一个单例类型,只有一个该类型的对象。不会有返回值的函数和运算符(例如 throw
语句或总是存在非本地异常的函数)逻辑上具有返回类型Nothing
,一种不包含对象的特殊类;也就是说,底层类型,即每种可能类的子类。(这反过来又使类Nothing
兼容各种类,允许 类型推段的正常工作。)
同样,一个if-then-else
“语句”实质上是一个表达式,它产生一个值,即两个分支其中一个的结果。这意味着这种代码块可以插入到任何需要表达式的地方,从而避免在Scala中需要使用到三元运算符:
|
|
出于该原因,return
语句在Scala中是不必要的,事实上也是不被鼓励的。如同在Lisp中一样,代码块中的最后一个表达式是该代码块的返回值,如果该代码块是函数的主体,代码块的值将由函数返回。
为了明确所有函数都是表达式,即使是返回Unit
的方法也是用到了等号
def printValue(x: String): Unit = {
println("I ate a %s".format(x))
}
或者等效地(使用类型推断,并省略不必要的大括号):
def printValue(x: String) = println("I ate a %s" format x)
类型推断
由于Scala具有类型推段特性,变量、函数返回值和许多其他表达式的类型通常可以省略,这是因为编译器可以推断出它们。例如:val x = "foo"
(对于不可变的常数或者不可变对象)或var x = 1.5
(对于可以改变其值的变量)。Scala中的类型推断本质上是局部的,这与Haskell,ML等其他更纯函数式语言中使用的更全局的Hindley-Milner算法形成对比。这样做是为了支持面向对象编程。因此,仍然某些类型仍需要被声明(最明显的是函数参数和递归函数的返回类型),例如
def formatApples(x: Int) = "I ate %d apples".format(x)
或者(为递归函数声明了返回类型)
def factorial(x: Int): Int =
if (x == 0)
1
else
x*factorial(x - 1)
匿名函数
在Scala中,函数是对象,并且有一个方便的语法来定义匿名函数。一个例子是表达式 x => x < 2
,它指定一个带有一个参数的函数,返回这个参数是否小于2。它相当于Lisp语言中的 (lambda (x) (< x 2))
。请注意,x
的类型和返回类型不需要显式的指定,通常可以通过类型推理判断出来;但是它们也可以被显式的指定,例如(x: Int) => x < 2
或者(x: Int) => (x < 2): Boolean
。
匿名函数表现为真闭包,这是因为它们自动捕获封在封闭函数环境内词法上可用的任何变量。这些变量即使在封闭函数返回后也是可用的,这与Java的匿名内部类不同,不需要声明为final。(如果这些变量是可变的,甚至可以修改它们,并且修改后的值将在下次调用匿名函数时可用。)
使用占位符变量可以让匿名函数更短:例如,下面的语句:
list map { x => sqrt(x) }
可以更简洁地写成
list map { sqrt(_) }
甚至
list map sqrt
不可变类型
Scala强制区分不可变(不可修改,只读)变量和可变变量,前者的值一旦赋值就不能更改,后者可以更改。不可变对象和可变对象之间也有类似的区别。当一个变量被声明时,必须进行区分:不可变变量是用val
声明,可变变量用var
。同样地,Scala中所有的集合对象(容器类型),例如链表,列表,集和哈希表也有可变与不可变之分,不可变变量被认为是更加基本的并且是默认的实现。不可变的变量是“持久”数据类型,这是因为它们创建一个包含旧对象并添加了新成员的新对象;这类似于在Lisp中构建链表的构建方式,在Lisp中,通过创建一个新的“cons”单元以及指向新元素(“head”)和旧列表(“tail”)的指针来添加新的元素。这导致并发非常简单——不需要锁,也不会修改任何的共享对象。不可变的数据结构也被有效地构建,从这方面而言,修改的实例重用大部分旧的实例数据而未使用/未引用的部分由垃圾回收收集。[26]
惰性(非热切)求值
默认情况下,Scala的求值策略是及早的(“热切的”)。换句话说,Scala会在表达式执行时对其进行求值,而不是在需要时进行。但是,可以使用lazy
关键字声明一个变量是非热切的(惰性的),这意味着直到第一次使用该变量时才会计算生成该变量值的代码。Scala中还有各种类型的非及早求值集合(例如Stream
类,非及早求值链表),任何集合都可以用view
方法变成为非及早求值的。非及早求值的集合为服务器生成的数据提供了良好的语义匹配,在这种情况下,生成列表的后续元素(进而触发对服务器的请求,可能位于网络上的其他地方)的求值代码只有在实际需要这些元素时才会被执行。
尾递归
函数式编程语言通常通过尾调用优化以允许广泛使用递归而不出现栈溢出问题。Java字节码中的限制使JVM上尾调用优化的实现变得复杂。一般来说,用尾调用调用自身的函数是可以被优化的,但是相互递归的函数不能。有人建议用Trampoline作为变通办法。[27] 自Scala 2.8.0发布(2010年7月14日)以来,Trampoline由Scala库通过scala.util.control.TailCall
被支持。函数可以用@tailrec
注释,在这种情况下,除非它是尾递归的,否则它不会编译。[28]
case类和模式匹配
Scala内置了对模式匹配的支持,它可以被视为更复杂的,可扩展的Switch语句,其中可以匹配任意数据类型(而不仅仅是简单类,如整数、布尔值和字符串),包括它们的嵌套。Scala提供一种被称为case类的特殊类, 它提供对模式匹配的自动支持,并可用于构建代数数据类型,这种数据类型在许多函数式编程语言中被使用。(从Scala的角度来看,case类只是一个普通类,编译器会自动地或手动指定地为它添加某些行为,例如,提供深度比较和散列的方法定义,以及在模式匹配过程中对case类的构造函数参数进行析构。)
使用模式匹配的快速排序算法示例如下:
def qsort(list: List[Int]): List[Int] = list match {
case Nil => Nil
case pivot :: tail =>
val (smaller, rest) = tail.partition(_ < pivot)
qsort(smaller) ::: pivot :: qsort(rest)
}
这里的想法是,我们将一个列表划分为小于轴的元素和大于等于枢轴的元素两个部分,递归地对每个部分进行排序,并将结果联合在一起,再将枢轴放在两者之间。这使用了和归并排序和其他快速排序算法相同的分而治之策略 。
match
运算符用于对存储在list
中的对象进行模式匹配。依次尝试每个case
表达式,看它是否匹配,并且首个匹配情况决定了执行结果。在这种情况下,Nil
仅匹配文字对象 Nil
,而pivot :: tail
匹配为非空列表,同时 根据给定的模式析构该列表。在这种情况下,相关代码将可以访问名为pivot的
局部变量,该变量指向列表的头部,和另一个变量tail
指向列表的尾部。请注意,这些变量是只读的,并且在语义上非常类似于Lisp和Scheme中使用let
运算符定义的变量绑定。
模式匹配也发生在局部变量声明中。在这种情况下,调用tail.partition
的返回值是一个 元组—在这种情况下,是两个列表。(元组不同于其他类型的容器,例如列表,这是因为它们总是大小固定,并且元素可以是不同的类型——尽管在这里它们都是相同的。)模式匹配是获取元组的两个部分的最简单方法。
_ < pivot
是一个对带有占位符变量匿名函数的声明;请参见上面关于匿名函数的部分。
上文的代码中出现了列表运算符 ::
(将元素添加到列表的开头,类似于Lisp和Scheme中的cons
)和:::
(这将两个列表附加在一起,类似于Lisp和Scheme中的append
)。尽管外表如此,但这两种操作符都没有“内在意义”。如上所述,任何符号字符串都可以作为函数名,并且应用于对象的方法可以写成“中缀”-形式而不带句点或括号。上面一行写道:
qsort(smaller) ::: pivot :: qsort(rest)
也可以这样写:
qsort(rest).::(pivot).:::(qsort(smaller))
以更标准的方法调用符号规范。(以冒号结尾的方法是右关联的,并绑定到右边的对象。)
偏函数
在上文的模式匹配示例中,match
运算符的主体是偏函数,它由一系列case
表达式组成,首个匹配的表达式即为结果,类似于Switch语句。在异常处理的try
语句中偏函数也被使用:
try {
...
} catch {
case nfe:NumberFormatException => { println(nfe); List(0) }
case _ => Nil
}
最后,偏函数可以单独使用,调用它的结果相当于对他进行match
。例如,上文的快速排序代码可以这样改写:
val qsort: List[Int] => List[Int] = {
case Nil => Nil
case pivot :: tail =>
val (smaller, rest) = tail.partition(_ < pivot)
qsort(smaller) ::: pivot :: qsort(rest)
}
这里声明了一个只读变量,其类型是从整数列表到整数列表的函数,并将其绑定到偏函数。(请注意,偏函数的单个参数从未被明确声明或命名。)但是,我们仍然可以像调用正常函数一样调用这个变量:
scala> qsort(List(6,2,5,9))
res32: List[Int] = List(2, 5, 6, 9)
Scala是一种纯粹的面向对象语言,因此,每个值都是一个对象。对象的数据类型和行为由类和特征描述。通过子类化和灵活的基于混入的组合机制扩展类抽象,以避免多重继承问题。
在Scala中,特征是Java中的接口的代替品。Java 8以下的版本中的接口受到高度限制,只能包含抽象函数声明。这导致了一些批评,即在接口中提供便利方法是别扭的(在每个实现中都必须重新实现相同的方法),并且以向后兼容的方式扩展已发布的接口是不可能的。因为特征总是混入类中,特征类似于混入类,因为它们几乎拥有常规抽象类的所有能力,只缺少类参数(Scala的类参数相当于Java的构造函数参数)。super
运算符在特征上表现比较特殊,它允许特征可以除了继承之外还使用组合的方式链接。以下示例是一个简单的窗口系统:
abstract class Window {
// abstract
def draw()
}
class SimpleWindow extends Window {
def draw() {
println("in SimpleWindow")
// draw a basic window
}
}
trait WindowDecoration extends Window { }
trait HorizontalScrollbarDecoration extends WindowDecoration {
// "abstract override" is needed here in order for "super()" to work because the parent
// function is abstract. If it were concrete, regular "override" would be enough.
abstract override def draw() {
println("in HorizontalScrollbarDecoration")
super.draw()
// now draw a horizontal scrollbar
}
}
trait VerticalScrollbarDecoration extends WindowDecoration {
abstract override def draw() {
println("in VerticalScrollbarDecoration")
super.draw()
// now draw a vertical scrollbar
}
}
trait TitleDecoration extends WindowDecoration {
abstract override def draw() {
println("in TitleDecoration")
super.draw()
// now draw the title bar
}
}
变量可以这样声明:
val mywin = new SimpleWindow with VerticalScrollbarDecoration with HorizontalScrollbarDecoration with TitleDecoration
mywin.draw()
的结果是:
in TitleDecoration
in HorizontalScrollbarDecoration
in VerticalScrollbarDecoration
in SimpleWindow
换句话说,尽管没有一个特征是继承另一个的,draw
的调用首先执行TitleDecoration
中的代码 (最后一个特征),然后(通过调用super()
)通过其他混入特征回到原线程,并最终返回到Window
中的代码, 。这类似于装饰模式,但它更简洁并且更不容易出错,这是因为它不需要显式封装父窗口、不需要通过显式转发实现不变的函数,或不需要依赖实例关系的运行时初始化。在其他语言中,可以在编译时通过一个长长的线性继承实现链来类似的效果,但与Scala相比有一个缺点,即必须为所有可能的混入组合声明一个线性继承链。
Scala配备了一个富有表现力的静态类型系统,该系统主要强制安全和抽象的连贯使用。然而,类型系统并不可靠。[29] 特别是,该类型系统支持:
Scala能够按使用情况推断类型。这使得大多数静态类型声明都是可以忽略的。除非编译器错误中表明需要声明,静态类型一般不需要显式声明。实际上,为了代码清晰起见,一些静态类型声明是必须的。
Scala中的一种常见技术,被称为“丰富我的库(enrich my library)”[30] (马丁·奥得斯基在2006年最初称之为“添加我的库(pimp my library)”;[25] 尽管有人因其负面含义与用词不当(pimp有拉皮条之义)[31]对这一措辞表示不满[32]),该技术允许像添加到现有类中一样使用新方法。这类似于C#的扩展方法概念,但是它更强大,因为该技术不仅限于添加方法,也可以,比如,用来实现新的接口。在Scala中,这种技术设计声明一个从“接收”方法的类型到装有原始类型新类型(通常是类)的隐式转换,并提供其他方法。如果找不到给定类型的方法,编译器则会自动搜索提供任何适用隐式转换,以提供所需要的类型。
此技术允许使用附加库将新方法添加到现有类中,只有导入附加库的代码才能获得新的功能,并且其他代码不受影响。
以下示例显示了用方法isEven
和isOdd
类型的丰富Int
类
object MyExtensions {
implicit class IntPredicates(i: Int) {
def isEven = i % 2 == 0
def isOdd = !isEven
}
}
import MyExtensions._ // bring implicit enrichment into scope
4.isEven // -> true
导入MyExtensions
的成员将扩展类IntPredicates
隐式转换带入范围。[33]
Scala的标准库包括对角色模型的支持,以及对标准的Java并发应用程序接口的支持。 Lightbend公司提供了一个平台[34] 该平台中有Akka,[35]一个提供基于角色模型并发的独立开源框架。Akka角色可能是分布式的或者与软件事务存储器(传输器)相结合的。其他的基于信道的消息传递通信顺序流程的实现有Communicating Scala Objects,[36] 或者简单地通过JCSP。
这里的角色就像一个带邮箱的线程实例。它可以通过system.actorOf
创建,重写receive
方法来接收消息,并使用!
(感叹号)方法发送消息。[37] 以下示例显示了一个可以接收消息并输出它们的EchoServer。
val echoServer = actor(new Act {
become {
case msg => println("echo " + msg)
}
})
echoServer ! "hi"
Scala,自2.9.0版起,以标准库中整合的Parallel Collections形式提供了内置的数据并行编程的支持[38]。
以下示例显示了如何使用并行集合来提高性能。[37]
val urls = List("https://scala-lang.org", "https://github.com/scala/scala")
def fromURL(url: String) = scala.io.Source.fromURL(url)
.getLines().mkString("\n")
val t = System.currentTimeMillis()
urls.par.map(fromURL(_))
println("time: " + (System.currentTimeMillis - t) + "ms")
除了对角色模型的支持和数据并行性,Scala还支持带有Futures和Promises的异步编程、软件事务内存和事件流。[39]
最著名的用Scala编写的开源集群计算解决方案是Apache Spark。此外,Apache Kafka,一种受Spark和其他流处理技术的欢迎发布-订阅模式消息队列,也是用Scala编写的。
版本号 | 发行日期 | 新特性 | 目前状态 |
---|---|---|---|
1.0.0-b2[44] | 8-Dec-2003 | _ | _ |
1.1.0-b1[44] | 19-Feb-2004 |
|
_ |
1.1.1[44] | 23-Mar-2004 |
|
_ |
1.2.0[44] | 9-Jun-2004 |
|
_ |
1.3.0[44] | 16-Sep-2004 |
|
_ |
1.4.0[44] | 20-Jun-2005 |
|
_ |
2.0[45] | 12-Mar-2006 |
|
_ |
2.1.0[44] | 17-Mar-2006 |
|
_ |
2.1.8[46] | 23-Aug-2006 |
|
_ |
2.3.0[47] | 23-Nov-2006 |
|
_ |
2.4.0[48] | 09-Mar-2007 |
|
_ |
2.5.0[49] | 02-May-2007 |
|
_ |
2.6.0[50] | 27-Jul-2007 |
|
_ |
2.7.0[51] | 07-Feb-2008 |
|
_ |
2.8.0[52] | 14-Jul-2010 |
|
_ |
2.9.0[53] | 12-May-2011 |
|
_ |
2.10[54] | 04-Jan-2013 |
实验性特性 |
_ |
2.10.2[64] | 06-Jun-2013 | _ | _ |
2.10.3[65] | 01-Oct-2013 | _ | _ |
2.10.4[66] | 18-Mar-2014 | _ | _ |
2.10.5[67] | 05-Mar-2015 | _ | _ |
2.11.0[68] | 21-Apr-2014 |
|
_ |
2.11.1[69] | 20-May-2014 | _ | _ |
2.11.2[70] | 22-Jul-2014 | _ | _ |
2.11.4[71] | 31-Oct-2014 | _ | _ |
2.11.5[72] | 08-Jan-2015 | _ | _ |
2.11.6[73] | 05-Mar-2015 | _ | _ |
2.11.7[74] | 23-Jun-2015 | _ | _ |
2.11.8[75] | 08-Mar-2016 | _ | _ |
2.11.11[76] | 18-Apr-2017 | _ | _ |
2.11.12[77] | 13-Nov-2017 | _ | _ |
2.12.0[78] | 03-Nov-2016 |
|
_ |
2.12.1[79] | 05-Dec-2016 | _ | _ |
2.12.2[76] | 18-Apr-2017 | _ | _ |
2.12.3[80] | 26-Jul-2017 | _ | _ |
2.12.4[81] | 17-Oct-2017 | _ | _ |
2.12.5[82] | 15-Mar-2018 | _ | _ |
2.12.6[83] | 27-Apr-2018 | _ | _ |
2.12.7[84] | 27-Sep-2018 | _ | _ |
2.12.8[85] | 04-Dec-2018 | 许可证更改为Apache v2.0发布的的首个Scala 2.12 | 目前版本 |
Scala经常被被人们与Groovy和Clojure,另外两种也使用JVM的编程语言,作比较。在类型系统中,在每种语言支持面向对象和函数编程的程度上,以及在它们的语法与Java语法的相似性上,都可以发现这些语言之间的巨大差异。
Scala是静态类型的,而Groovy和Clojure都是动态类型。这使得Scala的类型系统更加复杂和难以理解,但几乎允许所有[29]要在编译时捕获的类型错误,可以导致更快的执行。相比之下,动态类型需要更多的测试来确保程序的正确性,并且通常速度较慢,以便允许更大的编程灵活性和简单性。关于速度差异,当前版本的Groovy和Clojure允许可选的类型注释,以帮助程序在类型实际上是静态的情况下避免动态类型的开销。当使用最新版本的JVM时,这一开销会进一步减少,JVM已通过对动态类型参数定义方法的调用动态指令进行了增强。这些进步缩小了静态类型和动态类型之间的速度差距,尽管像Scala这样的静态类型语言在执行效率优先的情况下仍然是首选。
关于编程范例,Scala继承了Java的面向对象模型,并以各种方式扩展它。Groovy虽然也强面向对象,但更注重减少代码长度。在Clojure中,面向对象编程没有得到重视,函数编程是该语言的主要优势。Scala还有许多功能编程工具,其中包括高级函数式编程语言,例如Haskell,的特性,并试图在两种范例之间保持中立,让开发人员在两种范例之间进行选择,或者更频繁地,组合使用两种范例。
关于与Java的语法相似性,Scala就像Groovy一样,继承了很多Java的语法。另一方面,Clojure遵循Lisp的句法,在外观和哲学上都与Java不同。然而,因为Scala有许多高级特性,学习它也被认为是困难的。尽管Groovy也是一种功能丰富的语言,它并非如此,主要是因为它被主要设计成一种脚本语言。[来源请求]
截至2013年,所有基于JVM的语言(Clojure、Groovy、Kotlin、Scala)都远不如最初的Java语言受欢迎,后者通常排名第一或第二,[86][87] 并且随着时间的推移也在同时进化。
最受欢迎的编程语言排行,[88] 该排名追踪语言教程的搜索数量,在2018年4月Scala排名第15位,略有下降趋势。尽管紧随其后的是Kotlin,另一种一种基于JVM的语言,有很强的上升趋势,排名第16位,但是这使得Scala成为继Java之后最流行的基于JVM的语言。
编程语言受欢迎程度TIOBE指数[87]采用互联网搜索引擎排名和相关的出版物数量来评估语言受欢迎程度。截至2018年4月,它显示Scala排名第34位,在过去两年中下降了4位,但是—正如Bugs & Change Requests板块下所提到的—TIOBE意识到其使用搜索词的方法存在问题,他们使用的搜索词可能在一些编程语言社区中不常用。在这个排名中,Scala领先于一些函数式语言,比如Haskell (第42名),Erlang,但低于其他语言,如Swift (第15名),Perl(第16名),go(第19名)和Clojure(第30名)。
TkoughtWorks Technology Radat,是一组基于高级技术专家意见的半年度报告,[89] 建议Scala入选2013年度语言和框架类别。[90] 2014年7月,这一评估变得更加具体,现在指的是“Scala的优点”,它被描述为“要成功地使用Scala,你需要研究该语言并对那些适合你的部分有非常强烈的意见,创建你自己对Scala的优点的定义。”。[86]
RedMonk编程语言排名,根据GitHub上的项目和Stack Overflow上的问题数量对编程语言进行排名,它将Scala排名第14。[86] 在该排名中,Scala被放在第二阶梯语言中—在Go, PowerShell和Haskell之前,在Swift,Objective-C,Typescript和R之后。然而,在2018年的报告中,Scala的排名连续第三次下降,该排名质疑“Kotlin消耗了Scala多少可用氧气,来使其排名继续飙升”。[86]
在2018年版的“State of Java”调查中,[91] 该报告收集了5160名开发人员关于各种Java相关主题的数据,Scala在JVM上其他语言排名中排名第三。与去年的调查相比,Scala在其他JVM语言中的使用率下降了近四分之一(从28.4%降至21.5%),被Kotlin超越,后者从2017年的11.4%升至2018年的28.8%。
^Odersky, Martin (2008). Programming in Scala. Mountain View, California: Artima. p. 3. ISBN 9780981531601. Retrieved 12 June 2014..
^Potvin, Pascal; Bonja, Mario (24 September 2015). An IMS DSL Developed at Ericsson. Lecture Notes in Computer Science. 7916. arXiv:1509.07326. doi:10.1007/978-3-642-38911-5. ISBN 978-3-642-38910-8..
^Martin Odersky et al., An Overview of the Scala Programming Language, 2nd Edition.
^"Frequently Asked Questions - Java Interoperability". scala-lang.org. Retrieved 2015-02-06..
^Friesen, Jeff (16 November 2016). "Are checked exceptions good or bad?". JavaWorld. Retrieved 28 August 2018..
^Loverdo, Christos (2010). Steps in Scala: An Introduction to Object-Functional Programming. Cambridge University Press. p. xiii. ISBN 9781139490948. Retrieved 31 July 2014..
^Martin Odersky, "A Brief History of Scala", Artima.com weblogs, 9 June 2006.
^Odersky, M.; Rompf, T. (2014). "Unifying functional and object-oriented programming with Scala". Communications of the ACM. 57 (4): 76. doi:10.1145/2591013..
^Martin Odersky, "The Scala Language Specification Version 2.7".
^"Scala Team Wins ERC Grant". Retrieved 4 July 2015..
^"Commercial Support for Scala". 2011-05-12. Retrieved 2011-08-18..
^"Why We Invested in Typesafe: Modern Applications Demand Modern Tools". 2011-05-12. Retrieved 2018-05-08..
^"Open-source Scala gains commercial backing". 2011-05-12. Retrieved 2011-10-09..
^"Cloud computing pioneer Martin Odersky takes wraps off his new company Typesafe". 2011-05-12. Retrieved 2011-08-24..
^"Scala on Android". Retrieved 8 June 2016..
^"Scala 2.12.8 is now available!". 2018-12-04. Retrieved 2018-12-09..
^"Scala Js Is No Longer Experimental | The Scala Programming Language". Scala-lang.org. Retrieved 28 October 2015..
^https://web.archive.org/web/20221025115749/https://github.com/scala-js/scala-js/releases.
^Krill, Paul (15 March 2017). "Scaled-down Scala variant cuts ties to the JVM". InfoWorld. Retrieved 21 March 2017..
^Krill, Paul (2016-05-11). "Scala language moves closer to bare metal". InfoWorld..
^Expunged the .net backend. by paulp · Pull Request #1718 · scala/scala · GitHub. Github.com (2012-12-05). Retrieved on 2013-11-02..
^"Getting Started with Scala". scala-lang.org. 15 July 2008. Retrieved 31 July 2014..
^"Home". Blog.lostlake.org. Archived from the original on 31 August 2010. Retrieved 2013-06-25..
^Scala's built-in control structures such as if or while cannot be re-implemented. There is a research project, Scala-Virtualized, that aimed at removing these restrictions: Adriaan Moors, Tiark Rompf, Philipp Haller and Martin Odersky. Scala-Virtualized. Proceedings of the ACM SIGPLAN 2012 workshop on Partial evaluation and program manipulation, 117–120. July 2012..
^"Pimp my Library". Artima.com. 2006-10-09. Retrieved 2013-06-25..
^"Collections - Concrete Immutable Collection Classes - Scala Documentation". Retrieved 4 July 2015..
^Dougherty, Rich. "Rich Dougherty's blog". Retrieved 4 July 2015..
^"TailCalls - Scala Standard Library API (Scaladoc) 2.10.2 - scala.util.control.TailCalls". Scala-lang.org. Retrieved 2013-06-25..
^"Java and Scala's Type Systems are Unsound" (PDF)..
^Giarrusso, Paolo G. (2013). "Reify your collection queries for modularity and speed!". Proceedings of the 12th annual international conference on Aspect-oriented software development. ACM. arXiv:1210.6284. Bibcode:2012arXiv1210.6284G. Also known as pimp-my-library pattern.
^"Should we "enrich" or "pimp" Scala libraries?". stackexchange.com. 17 June 2013. Retrieved 15 April 2016..
^Gilbert, Clint (2011-11-15). "What is highest priority for Scala to succeed in corporate world (Should be in scala-debate?) ?". scala-lang.org. Retrieved 2019-05-08..
^Implicit classes were introduced in Scala 2.10 to make method extensions more concise. This is equivalent to adding a method implicit def IntPredicate(i: Int) = new IntPredicate(i). The class can also be defined as implicit class IntPredicates(val i: Int) extends AnyVal { ... }, producing a so-called value class, also introduced in Scala 2.10. The compiler will then eliminate actual instantiations and generate static methods instead, allowing extension methods to have virtually no performance overhead..
^"Lightbend Reactive Platform". Lightbend. Retrieved 2016-07-15..
^What is Akka?, Akka online documentation.
^Communicating Scala Objects, Bernard Sufrin, Communicating Process Architectures 2008.
^Yan, Kay. "Scala Tour". Retrieved 4 July 2015..
^"Parallelcollections - Overview - Scala Documentation". Docs.scala-lang.org. Retrieved 2013-06-25..
^Learning Concurrent Programming in Scala, Aleksandar Prokopec, Packt Publishing.
^Kops, Micha (2013-01-13). "A short Introduction to ScalaTest". hascode.com. Retrieved 2014-11-07..
^Nilsson, Rickard (2008-11-17). "ScalaCheck 1.5". scala-lang.org. Retrieved 2014-11-07..
^"Build web applications using Scala and the Play Framework". workwithplay.com. 2013-05-22. Retrieved 2014-11-07..
^Butcher, Paul (2012-06-04). "ScalaMock 3.0 Preview Release". paulbutcher.com. Retrieved 2014-11-07..
^"Scala Change History". scala-lang.org. Archived from the original on 2007-10-09..
^"Changes in Version 2.0 (12-Mar-2006)". scala-lang.org. 2006-03-12. Retrieved 2014-11-07..
^"Changes in Version 2.1.8 (23-Aug-2006)". scala-lang.org. 2006-08-23. Retrieved 2014-11-07..
^"Changes in Version 2.3.0 (23-Nov-2006)". scala-lang.org. 2006-11-23. Retrieved 2014-11-07..
^"Changes in Version 2.4.0 (09-Mar-2007)". scala-lang.org. 2007-03-09. Retrieved 2014-11-07..
^"Changes in Version 2.5 (02-May-2007)". scala-lang.org. 2007-05-02. Retrieved 2014-11-07..
^"Changes in Version 2.6 (27-Jul-2007)". scala-lang.org. 2007-06-27. Retrieved 2014-11-07..
^"Changes in Version 2.7.0 (07-Feb-2008)". scala-lang.org. 2008-02-07. Retrieved 2014-11-07..
^"Changes in Version 2.8.0 (14-Jul-2010)". scala-lang.org. 2010-07-10. Retrieved 2014-11-07..
^"Changes in Version 2.9.0 (12-May-2011)". scala-lang.org. 2011-05-12. Retrieved 2014-11-07..
^"Changes in Version 2.10.0". scala-lang.org. 2013-01-04. Retrieved 2014-11-07..
^Harrah, Mark. "Value Classes and Universal Traits". scala-lang.org. Retrieved 2014-11-07..
^Suereth, Josh. "SIP-13 - Implicit classes". scala-lang.org. Retrieved 2014-11-07..
^Suereth, Josh. "String Interpolation". scala-lang.org. Retrieved 2014-11-07..
^Haller, Philipp; Prokopec, Aleksandar. "Futures and Promises". scala-lang.org. Retrieved 2014-11-07..
^"SIP-17 - Type Dynamic". scala-lang.org. Retrieved 2014-11-07..
^"SIP-18 - Modularizing Language Features". scala-lang.org. Retrieved 2014-11-07..
^Prokopec, Aleksandar; Miller, Heather. "Parallel Collections". scala-lang.org. Retrieved 2014-11-07..
^Miller, Heather; Burmako, Eugene. "Reflection Overview". scala-lang.org. Retrieved 2014-11-07..
^Burmako, Eugene. "Def Macros". scala-lang.org. Retrieved 2014-11-07..
^"Scala 2.10.2 is now available!". scala-lang.org. 2013-06-06. Archived from the original on 2014-11-08. Retrieved 2014-11-07..
^"Scala 2.10.3 is now available!". scala-lang.org. 2013-10-01. Archived from the original on 2014-11-08. Retrieved 2014-11-07..
^"Scala 2.10.4 is now available!". scala-lang.org. 2014-03-18. Retrieved 2015-01-07..
^"Scala 2.10.5 is now available!". scala-lang.org. 2015-03-04. Retrieved 2015-03-23..
^"Scala 2.11.0 is now available!". scala-lang.org. 2014-04-21. Retrieved 2014-11-07..
^"Scala 2.11.1 is now available!". scala-lang.org. 2014-05-20. Retrieved 2014-11-07..
^"Scala 2.11.2 is now available!". scala-lang.org. 2014-07-22. Retrieved 2014-11-07..
^"Scala 2.11.4 is now available!". scala-lang.org. 2014-10-30. Retrieved 2014-11-07..
^"Scala 2.11.5 is now available!". scala-lang.org. 2015-01-08. Retrieved 2015-01-22..
^"Scala 2.11.6 is now available!". scala-lang.org. 2015-03-05. Retrieved 2015-03-12..
^"Scala 2.11.7 is now available!". scala-lang.org. 2015-06-23. Retrieved 2015-07-03..
^"Scala 2.11.8 is now available!". scala-lang.org. 2016-03-08. Retrieved 2016-03-09..
^"Three new releases and more GitHub goodness!". scala-lang.org. 2017-04-18. Retrieved 2017-04-19..
^"Security update: 2.12.4, 2.11.12, 2.10.7 (CVE-2017-15288)". scala-lang.org. 2017-11-13. Retrieved 2018-05-04..
^"Scala 2.12.0 is now available!". scala-lang.org. 2016-11-03. Retrieved 2017-01-08..
^"Scala 2.12.1 is now available!". scala-lang.org. 2016-12-05. Retrieved 2017-01-08..
^"SCALA 2.12.3 IS NOW AVAILABLE!". scala-lang.org. 2017-07-26. Retrieved 2017-08-16..
^"SCALA 2.12.4 IS NOW AVAILABLE!". scala-lang.org. 2017-10-18. Retrieved 2017-10-26..
^"SCALA 2.12.5 IS NOW AVAILABLE!". scala-lang.org. 2018-03-15. Retrieved 2018-03-20..
^"Scala 2.12.6 is now available!". scala-lang.org. 2018-04-27. Retrieved 2018-05-04..
^"Scala 2.12.7 is now available!". scala-lang.org. 2018-09-27. Retrieved 2018-10-09..
^"Scala 2.12.8 is now available!". scala-lang.org. 2018-12-04. Retrieved 2018-12-09..
^"The RedMonk Programming Language Rankings: January 2018"..
^"TIOBE Index for April 2018"..
^"Popularity of Programming Language Index"..
^"ThoughtWorks Technology Radar FAQ"..
^"ThoughtWorks Technology Radar MAY 2013" (PDF)..
^"The State of Java in 2018"..
^Greene, Kate (1 April 2009). "The Secret Behind Twitter's Growth, How a new Web programming language is helping the company handle its increasing popularity". Technology Review. MIT. Retrieved 6 April 2009..
^"Play Framework, Akka and Scala at Gilt Groupe". Lightbend. 15 July 2013. Retrieved 16 July 2016..
^"Scala, Lift, and the Future". Archived from the original on 13 January 2016. Retrieved 4 July 2015..
^"Why we love Scala at Coursera". Coursera Engineering. Retrieved 4 July 2015..
^"Apple Engineering PM Jarrod Nettles on Twitter". Jarrod Nettles. Retrieved 2016-03-11..
^"30 Scala job openings at Apple". Alvin Alexander. Retrieved 2016-03-11..
^David Reid & Tania Teixeira (26 February 2010). "Are people ready to pay for online news?". BBC. Retrieved 2010-02-28..
^"Guardian switching from Java to Scala". Heise Online. 2011-04-05. Retrieved 2011-04-05..
^"Guardian.co.uk Switching from Java to Scala". InfoQ.com. 2011-04-04. Retrieved 2011-04-05..
^Roy, Suman & Sundaresan, Krishna (2014-05-13). "Building Blackbeard: A Syndication System Powered By Play, Scala and Akka". Retrieved 2014-07-20..
^Pavley, John (2013-08-11). "Sneak Peek: HuffPost Brings Real Time Collaboration to the Newsroom". Retrieved 2014-07-20..
^Binstock, Andrew (2011-07-14). "Interview with Scala's Martin Odersky". Dr. Dobb's Journal. Retrieved 2012-02-10..
^Synodinos, Dionysios G. (2010-10-11). "LinkedIn Signal: A Case Study for Scala, JRuby and Voldemort". InfoQ..
^"Real-life Meetups Deserve Real-time APIs"..
^"Real time updating comes to the Remember The Milk web app"..
^"Senior Scala Engineer". Retrieved 2014-08-18..
^Novet, Jordan (2015-06-04). "Airbnb announces Aerosolve, an open-source machine learning software package". Retrieved 2016-03-09..
^Kops, Alexander (2015-12-14). "Zalando Tech: From Java to Scala in Less Than Three Months". Retrieved 2016-03-09..
^Calçado, Phil (2014-06-13). "Building Products at SoundCloud—Part III: Microservices in Scala and Finagle". Retrieved 2016-03-09..
^Concurrent Inc. (2014-11-18). "Customer Case Studies: SoundCloud". Retrieved 2016-03-09..
^Skills Matter (2015-12-03). "Scala at Morgan Stanley (Video)". Retrieved 2016-03-11..
^Greg Soltis. "SF Scala, Greg Soltis: High Performance Services in Scala (Video)". Retrieved 2016-03-11..
^Lee Mighdoll. "Scala jobs at Nest". Retrieved 2016-03-11..
^Nurun. "Nurun Launches Redesigned Transactional Platform With Walmart Canada". Retrieved 2013-12-11..
^André K. Horie (2017-01-31). "Rewriting Duolingo's engine in Scala". Retrieved 2017-02-03..
^"HMRC GitHub repository"..
^Krikorian, Raffi (17 March 2015). O'Reilly Software Architecture Conference 2015 Complete Video Compilation: Re-Architecting on the Fly - Raffi Krikorian - Part 3 (video). O'Reilly Media. Event occurs at 4:57. Retrieved 8 March 2016. What I would have done differently four years ago is use Java and not used Scala as part of this rewrite. [...] it would take an engineer two months before they're fully productive and writing Scala code..
^Scott, Kevin (11 Mar 2015). "Is LinkedIn getting rid of Scala?". quora.com. Retrieved 25 January 2016..
^Hale, Coda (29 November 2011). "The Rest of the Story". codahale.com. Retrieved 7 November 2013..
暂无