Scala flexible syntax: bad or good?

Scala 风格太多变了,做一件事可以有N 条路。

比如声明一个方法:

val multiply = (x:Int) => x * x
def multiply(x : Int) : Int = {
  return x * x;
}

这方法都可以用multiply(3) 来调用。当然你完全可以说前一种是把匿名方法赋值给常量multiply。但是在我看来,这只是修辞上的问题,对结果并无影响。如果说上面这种还有说辞,那请看下面的代码:

val aaa = 1 to 3
val bbb = 1.to(3)

这两种形式是完全等价的,只是在写法上有区别而已。

在语句分割上Scala 也采取了比较灵活的方式,一行是一条语句,如果想把两条语句放在同一行,可以用分号分隔。上面的常量声明可以像下面一样写在一行:

val aaa = 1 to 3;    val bbb = 1.to(3);

当然即使分开写成两行,也可以把分号用作一条语句的结束。

上面只是最基本的两点,还有其他的一些诡异的地方。老实说这很大程度上是因为我对Scala 还不是那么熟悉,以致我在刚开始摸Scala 的时候无所适从,嗯,其实刚开始摸什么都是一样-_-!

只有一个参数的方法调可以用 object method argument 的方式,Python 也有类似的情形。不过对Scala,我采用了对待Python 同样的方式,直接忘记这种写法,只记得object.method(argument),毕竟这和多个参数的写法一致。

还有一处乍看起来很迷惑,但是如果糊里糊涂起来却很自然的地方,Scala 的类型推断。大部分的强类型语言中,我们都习惯于先声明变量的类型,然后再进行操作,像继承自C 的编程语言,基本都是这个路子。弱类型语言不是这样的,弱类型基本是采用了推断的方式,即看变量被赋予了什么样的值。比如看下面的循环:

for ( i <- 1 to 2 ) {
  println( "No." + i )
}

变量i 并没有指定是何类型, 但是完全可以通过1、2 来推定是Int 。 很自然不是吗?

使用Scala,既可以写命令式的代码,也可以写函数式的代码。命令式的代码就不用说了,C家族的语言到现在基本都是命令式的。函数式的代码可以把函数作为方法传到函数内,下面是个简单的例子:

val sqr = (ss : String, x : Int) => ss + x * x;
def call(f : ((String, Int) => String), s : String, n : Int) : String = {
  f(s, n);
}
// sqr is a function
println(call(sqr, "3*3=", 3));

这个例子很简单,就是定义了一个方法,然后作为另一个方法的参数来调用。这个方法只能示例函数式大概的样子,函数编程的强大完全体现不出来。函数式编程最大的特点应该是每个变量只能初始化一次,一旦初始化之后就再也不能改变它的值,在Scala 中这样的变量用val 来定义。下面是另一个稍微复杂点的例子:

val nn = (0 to 10);
val whatisthis = nn.reverse.map(e => e + 10).foreach(x => print(x + ","));
println(); // just for a new line
nn.foreach(e => print(e + ","));

输出结果是:

20,19,18,17,16,15,14,13,12,11,10,
0,1,2,3,4,5,6,7,8,9,10,

稍微解释一下,nn 的类型为scala.collection.immutable.Range。这里,我们先把集合反转,再把每个元素加10,回头坚持最开始的nn,却发现没有改变。(whatisthis 什么都不是)

函数式的编程语言可以写出非常强大,但是短小精悍的代码,当然前提是习惯了函数式的思路。

Scala 是一门溶命令式和函数式为一身的编程语言。这当然是一个优势,熟悉命令式或者函数式编程方法的兄弟,都可以充分利用Scala 强大的库。但是对新手来说,如果陷入对两种编程方式的艰难选择而不能自拔,那么Scala的这种优势基本上就变成了一个灾难。所以,我强烈不建议新手们把Scala 用到生产环境中。只有对Scala 非常熟悉,能够熟练的应用两种思路最直接地解决问题,这时候才能真正把Scala 用于生产。毋庸置疑的,Scala 生产力非常强大,绝对值得投资。(非广告)

在使用Scala 时有这么多可用的方法可以选择,改如何是好呢?其实每种方法都有她的优点,不能说哪种是最好的,因为每个人看法不一定一样,而且不同的方式在特定的情况下可能分别都是最优方案。就我个人来讲,我倾向于在一份代码中采用相同的编码方式。在多人(甚至只要超过两个人)团队中,代码风格泛滥一定会成为障碍,尤其是对新加入团队的成员来说。在我的团队中,我会要求以下几点:
0/ 要么命令式、要么函数式,只能有一个主流,另一个严格限制在很小范围内
1/ 用大括号分割代码段,光凭换行不能充分利用文本编辑器
2/ 用分号结束语句
3/ 只有在非常明显的地方才省略类型声明,比如前面for 的例子
4/ 不用object method argument 这种方式,统一函数调用方式
5/ 变量统一用val 声明
6/ 不省略函数返回的return 关键字

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>