11Aug/102
Scala笔记1
最近在看Scala,把笔记贴过来存档。
- Scala基于JVM,通过scalac编译成JVM字节码。不同于Groovy(同样是跑在JVM上),Scala是静态类型的,因此可以支持泛型和多态等特性。Scala完全使用自己的规则创建,因此相对于Groovy来说学习成本更高(Groovy其实就是Java的强化?简化?版)。而且因为基于JVM,因此可以很好的和现有Java项目整合,在Scala中可以直接使用Java现成的无数类库。
- Scala通过var和val定义变量。var定义可变量,val定义不可变量,类似Java中的final,一旦初始化赋值后就无法改变。Scala鼓励尽可能的使用val让类和方法获取原生的线程安全性,同时通过val和闭包(方法对象)的使用来支持函数式编程。当然Scala也可以使用Java抠腚们熟悉的命令式来书写。
- 既然Scala支持FP,因此它确实支持尾递归优化。只不过受制于JVM,只能做到简单的尾递归优化,在比较复杂的情况下无法确实优化。下面的代码清单是一个尾递归的例子,递归了一亿次,一切正常。
object Main { def main(args: Array[String]): Unit = { println(doSum(100000000L, 0)) } def doSum(n: Long, sum: Long): Long = { if (n == 0L) { sum } else { doSum(n - 1, sum + n) } } } - Scala中万物皆对象,它不像Java那样割裂开原始类型和对象。同时Scala有自己的富包装类,比如RichInt,提供一些好用的方法如RichInt的to,RichString的reverse。但是由于富包装类的存在,会出现一个陷阱。见下面的代码清单。
2.toString() // 直接对一个整数调用toString方法 2 to 3 // RichInt的to方法,返回一个Range对象用于迭代。这里语法有点奇怪,下面会提到。 "ana".reverse == "ana" // false 因为是RichString和String的比较。用==比较有违Java的直觉,下面会提到。
- Scala中万物皆方法(好吧其实我指的是它没有操作符!而且方法其实也是对象),所有的+、-、*、/等操作符其实都是方法,Scala使用方法名第一个字符的优先级来取代操作符优先级。同时为了配合这个特性,Scala语法允许对无参数或者只有一个参数的方法调用省略点号和括号。下面的代码清单演示了这个特性。
2.toString() // ---- 2.toString // 这都是同样的调用 2 toString; // --- 注意这里使用了分号,在必要的时候使用分号告诉Scala语句结束了 // --- 绝大部分时候Scala自己会判断到语句的结束,解放你的右手小拇指 2 to 3 // --- 2.to(3) // 这两个也是一样的 2 * 3 // --- (2).*(3) // 这两个还是一样的,使用(2)是因为2.会被识别成Double:2.0
基于这个特性,我们甚至可以在Scala之上构筑自己的语言。
- Scala中的==操作和Java中的不同,==由Scala类结构最上层的Any实现为final的方法,其实现就是调用Java经典的equals方法。在Scala中==的表现永远和equals相同,!=则永远和equals相反。因此虽然==被声明为final而不可重载,但我们可以通过重载equals支持自定义类型的==操作。如果你需要Java中经典的==操作符的时候,你可以使用eq。下面的代码清单分别使用了这两个方法。
object Main { def main(args: Array[String]): Unit = { val p1 = new Point(1, 1) val p2 = new Point(1, 1) println(p1 == p2) // true ==会调用重载的equals方法 println(p1.==(p2)) // true ==同样是个方法 println(p1 eq p2) // false Java中的引用比较 } } private class Point(_x: Int, _y: Int) { def x = _x def y = _y override def toString: String = { x + ":" + y } override def equals(other: Any): Boolean = { other != null && other.isInstanceOf[Point] && { val o = other.asInstanceOf[Point] o.x == this.x && o.y == this.y } } } - 闭包、集合、元组、多行原始字符串等现代动态语言中的特性都存在与Scala中,而Java则都没有(集合较复杂而不好用)。同样的省略分号,自动返回最后一句语句的执行结果等简化语法的特性也存在与Scala中。同时Scala的类型推断机制使得静态类型的Scala也拥有动态类型语言那样的书写风格和表现力。而为了使类型推断更好的工作,应当尽量避免在代码中显示的return,如果使用了显示的return,则可能必须为方法声明返回类型。
- Scala中的另一个陷阱是它的赋值操作返回值是Unit(你可以认为是Java中的void),因此像a=b=c=1这样的连续赋值会报错,应该使用下面代码清单的赋值方式。
val a, b, c = 1 // a、b、c都会被初始化为Int:1 val (d, e, f) = (1, 2, 3) // d、e、f分别被初始化为Int:1、Int:2、Int:3
未完待续……
August 11th, 2010 - 09:27
CPP城续缘笑而不语…
August 11th, 2010 - 09:43
快去学Python,我们这儿有个缺职。