请注意这篇文章是写给对Java不太爽的同学,可能带有强烈的感情色彩。
Scala号称结合函数式和面向对象,其实它是一门100%的面向对象语言,里边的所有表达式都是对象,而函数式特性其实只是在上面加的一层语法糖,比如tuple和for yield .
tuple可以匿名地把一些值放在一起,并且是类型安全的,而case class相当于带名字的tuple,两者都是不可变的,要传修改后的值需要obj.copy(...)。不可变数据类型的一个好处是不需要再去费力跟踪变量到底在哪里变了,但是同时Scala也支持可变数据类型(var)。
定义类的语法也要简洁很多,就像定义一个函数一样:
class scalaBasics(name: String,value:String="abc") {
}
for yield则是针对Monad的语法糖,而Monad可以视为一种容器的性质,这种性质可以让你注意力集中在容器里的元素,而容器本身的特性则“自动”处理了,比如Seq和Option都是容器(Scala里边不鼓励使用try catch,推荐的是Option):
val optMonad: Option[(Int, Int)] = for {
a
b
} yield (a, b,a*b)
// = Some((1,2,2))
val seed: Seq[Int] = 1 to 10
val listMonad0: Seq[(Int, Int, Int, Int)] = for {
i
j
res = i + j
res1 = i * j
} yield (i, j, res, res1)
// = 1到10 加和乘的所有组合
代数数据类型(ADT):
sealed trait Tree
case class Leaf(i: Int) extends Tree
case class Node(l: Tree, r: Tree) extends Tree
另外,Scala调用Java库是无缝的,反过来的话就看情况了
Scala的缺点一个是Macro元编程目前还比较混乱,但是有个叫Shapeless库把一些本来需要用宏的场景给包括进去了,用起来方便了很多:
//把tuple当List,同时保留类型安全
scala> (23, "foo", true).head
res0: Int = 23
scala> (23, "foo", true).tail
res1: (String, Boolean) = (foo,true)
scala> (23, "foo", true).drop(2)
res2: (Boolean,) = (true,)
scala> (23, "foo", true).take(2)
res3: (Int, String) = (23,foo)
还可以用这个库写出输入是所有的Case class的函数,比如全自动的JSON 序列化/反序列化库(netvl/picopickle)。
生态方面的话,AKKA actor作为Erlang系风格的库,用来开发分布式系统是很酷炫的,Akka Cluster封装了很多分布式需要用的Common pattern,比如Singleton Akka Documentation.
更多对比请看https://www.toptal.com/scala/why-should-i-learn-scalawww.toptal.com