2.1 条件表达式·
if/else表达式有值,这个值就是跟在if或else之后的表达式的值。如:
if (x > 0) 1 else -1
因此可以将if/else表达式的值赋值给变量:
val s = if (x > 0) 1 else -1
这与以下语句的效果是一样的:
if (x > 0) s = 1 else s = -1
第一种写法可以用来初始化一个val,第二种写法只能初始化var。
在scala中,每个表达式都有一个类型。
if (x > 0) "positive" else -1
上述if分支,一个是java.lang.String,而另一个分支是Int。它们的公共超类型叫做Any。
2.2 语句终止
省略分号可以。使用分号也行。注意的是在命令行模式下一行的结束问题。
2.3 块表达还是和赋值
在Scala中,{}块包含一系列表达式,其结果也是一个表达式。块最后一个表达式的值就是块的值。
val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx*dx + dy * dy)}
Scala中的Unit类型等同于Java中的void,这个类型只有一个值,写作()。
赋值动作本身是没有值得,更严格的说,它们的值是Unit类型的。也就是
n=-1
这个赋值语句除了使n为-1之外,语句本省也有一个值,这个是是Unit。所以下面的连续赋值不能实现与Java中相同的目的:
x = y = -1
与= -1的值是()。
2.4 输入和输出
print
println
printf("Hello, %s ! You are %d years old.\n","Fred",42)
还有一些其他函数
readLine
readInt
readDouble
readByte
readShort
readLong
readFloat
readBoolean
readChar
2.5 循环
while (n > 0) {
r = r * n
n -= 1
}
scala的for循环有所不同
for (i <- 1 to n)
r = r * i
1 to n 产生一个Range,让i去遍历这个Range中的所有元素
遍历字符串或者数组时,你通常要使用0到n-1的区间。此时可以使用until方法。而不是to方法。util方法返回一个并不包含上限的区间。
break
import scala.util.control.Breaks._
breakable {
for (...) {
if (...) break;
}
}
2.6 高级for循环和for推导式
可以以 变量 <- 表达式
的形式提供多个生成器:
for (i <- 1 to 3; j <- 1 to 3) print ((10 * i + j) + " ")
每个生成器都可以带一个守卫,以if开头的Boolean表达式
for (i <- 1 to 3; j <- 1 to 3 if i != j ) print ((10 * i + j) + " ")
你可以使用任意多的定义,引入可以在循环中使用的变量:
for (i <- 1 to 3; from = 4 - i; j <- from to 3) print ((10 * i + j) + " ")
如果for循环体以yield开始,则该循环会构造出一个集合,每次迭代生成集合中的一个值:
for (i <- 1 to 10) yield i % 3
这个就是for推导式,它生成的集合与它的第一个生成器是类型兼容的。
for (c <- "Hello"; i <- 0 to 1) yield (c + i).toChar
2.7 函数
一般地,我们不用写函数的返回值类型
def fac(n: Int) = {
var r = 1
for (i <- 1 to n) r = r * i
r
}
上述函数的返回值,是表达式块的最后一个r的值。可以看到,我们也不用写return语句。
但是对于递归函数,我们需要指定返回值的类型:
def fac(n: Int): Int = if (n <= 0) 1 else n * fac(n - 1)
如果没有返回类型,Scala编译器无法校验n * fac(n-1)的类型是Int。
2.8 默认参数和带名参数
调用某些函数时,并不显式地给出所有的参数值,对于这些函数我们可以使用默认参数。
def decorate (str: String, left: String = "[" , right: String = "]") =
left + str + right
调用函数时可以提供带名的参数。
2.9 变长参数
def sum(args: Int*) = {
var result = 0
for (arg <- args) result += arg
result
}
可以使用任意多的参数来调用它
def recursiveSum(args: Int*): Int = {
if (args.length == 0) 0
else args.head + recursiveSum(args.tail:_*)
}
2.10 过程
过程是定义函数时,不需要返回值的,也就没有函数名后面的等于号
def box(s: String) {
var border = "-" * s.length + "--\n"
println(border +"|" + s + "|\n" + border)
}
其实,过程返回的是一个Unit类型,:
def box(s: String) : Unit = {
...
}
2.11 懒值
当val被声明为lazy时,它的初始化将被推迟,直到我们首次对它取值。
lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
注意下面三种取值的时间
val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
//在words被定义时即被取值
lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
//在words被首次使用时即被取值
def words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
//在每次words被使用时取值
2.12 异常
scala的异常机制和Java或C++一样。当你抛出异常时,比如:
throw new Illega;ArgumentException("x should not be negative")
当前的运算被终止,运行时系统查找可以接受IllegalArgumentException的异常处理器。
在scala中,"受检"异常不支持。受检查的异常在编译器被检查。在java中,如果你的方法可能会抛出IOException,你必须做出声明。
try {
procerss(new URL("http://horstman.com/fred-tiny.gid"))
} catch {
case _: MalformedURLException => println("Bad URL: " + url)
case ex: IOException => ex.printStackTrace()
}
练习
def (x : Integer) = {
if (x > 0)
x.sigsum = 1
else if (x < 0)
x.sigsuim = -1
else
x.sigsum = 0
}
for (i <- 0 to 10; j = 10 -i ) println(j)
def countdown(x : Int) {
for (i <- 0 to n)
println(n - i)
}
var sum = 1L
for (c <- "Hello") sum *= c.toLong
println(sum)
def product(s: String) : Long = {
var sum = 1L
for (c <- s)
sum = sum * c.toLong
sum
}
def product(s: String) : Long = {
if (s.size == 1)
return s(0).toLong
else
return s.head.toLong * product(s.tail)
}
def calculate(x: Int, n: Int) : Long = {
if (n == 0) 1
else if (n < 0) 1 / calculate(x, -n)
else if( n % 2 == 0) calculate(x,n/2) * calculate(x,n/2)
else x * calculate(x,n-1)
}