您的位置:首页 > 其它

Scala for the Impatient - (Chapter 1, 2)

2013-08-26 13:57 330 查看

Declaring values and variables

scala推荐使用val声明变量,除非你需要修改变量内容才使用var

scala中变量的类型要写在变量名后,根据stackoverflow上众位大神的解释,好处如下:

名称比类型更重要,这样做可以突出强调变量本身,而不是变量的类型。在scala中,类型推断应该交给编译器完成,写代码的人更应该关注如何使用

代码写起来更整洁,比如很多行由val,var,def开头的变量声明

使用diff来比较的时候,可以很清楚的看到某个变量的类型变化

Java中的Primitive Types都被重新定义成Class实现,要多多注意这些类的使用方法

Integer - RichInt

Double - RichDouble

Char - RichChar

String - StringOps

Arithmetic and Operator Overloading

Operator实际上都是类的各种方法,比如这个加法

a + b

a.+(b)


注意++操作符是不存在的

Calling Functions and Methods

比如Java中的Math.abs(a), method必须得跟在一个类的后面。到了scala,方法是可以脱离类存在的,就好像其他语言中的build-in functions一样,比如

import scala.math._

sqrt(20)
pow(2, 4)
min(3, Pi)


scala中没有static method的说法,但是它提供了一种叫singleton objects的类似功能,即class可以有一个companion object来提供static methods (具体的用法后面解释)

如果是没有参数的method,写的时候就不要加括号了,啰嗦。一般的,如果该方法不会对象,那也可以不写括号。

The apply Method

没太看懂这段的介绍,stackoverflow上一个解释

Conditional Expressions

scala中的if/else语句是有返回值的,比如下面这个例子。很明显,scala的写法要更加简洁,

// scala
val s = if (x>0) 1 else -1

// java
int s;
if (x>0) { s = 1; } else { s = -1; }


scala中每个表达式实际上都有一个类型,就是它的返回类型。

如果是if/else这种可能使用mixed-type,返回的就是它们的supertype。

val s = if (x>0) "possible" else -1   // s is Any


如果只是if,

val s = if (x>0) "possible"

// equals: if (x>0) "possible" else ()
// () is Unit, ()可以看作是占位符, Unit就是void


Statement Termination

scala中默认不写分号,除非一行有多条语句,很好的语法特性

Block Expressions and Assignments

跟Java一样,{ }包围着的就是一个Block,最后一句就是整个Block的值 (赋值语句的没有返回值,或者说返回的是Unit)

Input and Output

print:

print("Answer is ")
println("Answer is ")
printf("Anser is %s, with %d", "fred", 42)


read:

val name = readLine("Your name: ")
val age = readInt()
val salary = readDouble()

// readInt, readDouble, readByte, readShort, readLong, readFloat, readBoolean, readChar


Loops

while, do-while都和java的用法一样

for的变化很大,实际上for并不常用

for (i <- expr)  // 意思是i将遍历右侧表达式中的每一个值


Advanced for Loops and for Comprehensions

一些基本的写法

for (i <- 1 to 3; j <- 1 to 3) print((10*i + j) + " ")
// 11, 12, 13, 21, 22, 23, 31, 32, 33

for (i <- 1 to 3; j <- 1 to 3 if i != j) print((10*i + j) + " ")
// 12, 13, 21, 23, 31, 32

for (i <- 1 to 3; from = 4 - i; j <- from to 3) print((10*i + j) + " ")
// 13, 22, 23, 31, 32, 33


stackoverflow上关于for comprehension的讨论

for (c <- "Hello"; i <- 0 to 1) yield (c + i).toChar
// String: HIeflmlmop

for (i <- 0 to 1; c <- "Hello") yield (c + i).toChar
// Char array: ['H', 'I', 'e', 'f', 'l', 'm', 'l', 'm', 'o', 'p']


Functions

scala中的Function可以独立于class存在

def abs(x: Double) = if (x > 0) x else -x


除非是递归,否则不需要指定Function的返回值,编译器会自动推断返回值的类型

Default and Named Arguments

scala中,你可以为函数参数指定默认值

def decorate(str: String, left: String = "[", right: String = "]") = left + str + right


调用函数的时候,也可以不按参数顺序,只要提供名称就好

decorate(left = ">>>", str = "wrap me", right = "<<<")
// >>>wrap me<<<


Variable Arguments

// 此时的参数类型是Seq
def sum(args: Int*) = {
var result = 0
for (arg <- args) result += arg
result
}


如果你有了一个Sequence,你需要告诉编译器你希望传入的时候作为sequence来处理:

val s = sum(1 to 5: _*)


更加FP的sum实现:

def sum(args: Int*) : Int = {
if (args.length == 0) return 0
else args.head += sum(args.tail: _*)
}

// args.head is initial element
// args.tail is a sequence of all other elements


Procedues

没有返回值 (或者说返回值是Unit) 的Function,就叫做Procedue

// 定义的时候不需要 =
def box(s: String) {
println("|" + s + "|\n")
}
// 或者
def box(s: String) : Unit = {
println("|" + s + "|\n")
}


Lazy Values

只要变量声明时候加了lazy,你不用就不会被初始化

lazy val words = scala.io.Source.fromFile("/tmp/non-existed.log").mkString
// 编译没问题。运行时,除非有代码调用到了words,否则不会去检查这个文件读取的时候有没有问题


val, lazy and def

val words = scala.io.Source.fromFile("/tmp/my.log").mkString
// Evaluated as soon as words is defined

lazy val words = scala.io.Source.fromFile("/tmp/my.log").mkString
// Evaluated the first time words is used

def words = scala.io.Source.fromFile("/tmp/my.log").mkString
// Evaluated every time words is used


Exceptions

scala中没有checked exception, 意味着写代码的时候不需要声明一堆throw AAAException, BBBException.

在try-catch中,异常捕捉是基于pattern-matching的,跟java相比显得格外简洁

try {
process(new URL("http://www.example.com/test.gif"))
} catch {
case _: MailFormedURLException => println("Bad URL: " + url)
case ex: IOException => ex.printStackTrace()
}
// use _ for the variable name if you don't need it


在try-finally中,finally跟java一样,无论如何都会被执行的

in = new URL("http://www.example.com/test.gif").openStream()
try {
process(in)
} finally {
in.close()
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: