Scala系列:控制结构与函数
在java语言中,表达式表示值,语句表示执行动作。 例如:表达式1+1表示值;thread.start()表示执行动作。
所有语法结构都有值,那怕是不存在用Unit类型.
if/else语句
有值,为跟在if或else之后的表达式的值。
例:val s = if(x > 0) 1 else 0;
等同于var s:Int = 0; if (x > 0) s = 1 else s = 0;
val s2 = if (x > 0) "string" else 1;
s2的类型为Any
val s3 = if (x > 0) 1;
s3的类型也是Any,但x <= 0时s3的值为Unit, Unit类表示“无有用值”,写做()
没有switch语句
语句终止
一行一条语句行尾不需要分号
一行多条语句需要使用分号把它们隔开
较长语句分两行时,在第一行尾部不要用语句结束的符号结束,通常使用一个操作符。如:
val s = "sssssssssssssssssssssssssss" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + //告诉解析器这里不是语句的结尾
"ccc" + "dd"
块表达式和赋值
{}块包含一系列表达式,其结果是块中最后一个表达式的值。
例:val s = {1+2; 2+3} //s的值为5
注意:赋值语句的返回值是Unit类型,写作()
例:val u = {b = 3}
x = y = 1,结果为x的值Unit,y的值1。因为y = 1语句的值为Unit;
输入与输出
print()
println() 打印完后追加一个换行符
printf()具有c风格, %s , %d, %f,
输入:
readLine("tips"):从控制台读取一行,"tips"为输出提示
readDouble, readFloat, readByte, readChar readShort, readInt, readLong, readBoolean
循环
while循环
while (n > 0){
// TODO
}
for循环
for (i <- 1 to n) {
// TODO
}
for的参数表达式说明:让变量i遍历<-右边表达式的所有值。
通常在遍历时使用util,until返回一个不包括上限的区间。例:0 until 2,表示Range(0, 1)
注:scala没有类似java的for(;;)型for语句
for高级特性:
循环体带yield,即for推导:
val z = for (i <- 0 until 3) yield i;
z的值为Vector(0, 1, 2)
多个生成器、守卫、变量定义:
for (i <- 0 until 5; j <- 3 until ;) { println(i, j)} //多个生成器
for (i <- 0 until 5; from = 4 - i; j <- from until 5) {} //变量定义
for (i <- 0 until 5; from = 4 - i; j <- from until 5 if i != j) {} //每个生成器可以带一个守卫,注意if前没有分号
没有break和continue
需要时怎么办?
1、使用变量控制
2、外层嵌套函数,使用return进行break;
3、使用异常机制,抛出异常与捕获异常控制。
scala提供的:
1 import scala.util.control.Breaks.break 2 import scala.util.control.Breaks.breakable 3 4 breakable { 5 for (i <- 0 until 2) { 6 println(i) 7 if (i == 1) break; 8 } 9 }
函数
定义函数只需要给出函数名、参数和函数体
def 函数名[(参数名:参数类型,…)][: 返回类型]= {
// function body
}
注:[]表示可选,只要函数不是递归的就不需要指定函数的返回类型;scala会自动推断函数的返回类型。
函数体最后一个表达式的值就是函数的返回值,当然也可以用return显式返回。
如果函数没有参数,括号可以省略,但调用时也不能带括号。
默认参数和带名参数
1 def test(str: String, left: String = "[", right: String = "]") = left + str + right 2 test("hello") // 返回[hello] 3 test("hello", right = ">>") 4 test("hello", left = "<", right = ">") 5 test("hello", right = ">")
变长参数:
1 def sum(args: Int*) = { 2 var result: Int = 0 3 for (arg <- args) result += arg 4 result 5 }
可以使用合意多的参数来调用该函数
sum(1, 2, 3)
如果有了一个值的序列,不能直接调用,得转化
val s = sum(1 to 10: _*) // _*将1 to 10当作参数序列处理。
val s = sum(1 to 10) // 会报错
此语法的用处是递归
1 def recursiveSum(args: Int*): Int = { 2 if (args.length == 0) 0 3 else args.head + recursiveSum(args.tail: _*) 4 }
args.head表示args的首个元素,而tail表示所有其它的元素。
过程:
没有返回值的函数,函数体前不带“=”。
lazy:
lazy val words = Source.fromFile("readme2.txt").mkString
函数第一次调用时加载
也有额外开销,每次访问懒值,都会调用一个方法以线程安全的方式检查值是否已经初始化
异常
方法不用带类似throw IOException的签名
try{
} catch {
case _: IOException => println("xx") // 不需要使用异常对象,可以使用_来代替异常名。
case e: Exception => e.printStatckTrace()
} finally {
}