scala学习之路(二)控制结构和函数
Scala(二)控制结构和函数
- 条件表达式
- 语句终止
- 块表达式和赋值
- 输入和输出
- 循环
- 函数
- 默认参数和带名参数
- 变长参数
- 过程
- 懒值
- 异常
1. 条件表达式
if/else 语法结构和Java一样。但是scala中if/else有返回值,这个值就是在if或else之后的表达式的值
if (x>0) 1 else -1 //返回值是1或-1
val s = if(x>0) 1 else -1 等价于 if(x>0) s=1 else s=-1
两个表达式的都是相同类型时,返回类型是相同的;
如果两个表达式返回类型不同,返回类型是Any公共超类型
***因为每个表达式都必须有返回值,如果不想返回值,则可以用Unit类写做 ()
if (x>0) 1 else () //返回值是1或什么都没有
***注意:在REPL中同一时间只能看到一行代码。
if (x > 0 ) 1
else if (x==0) 0 else -1
这将不知所措
可以使用花括号
if (x > 0){ 1
}else if (x==0) 0 else -1
如果想粘贴块状代码,而不想担心这个问题可以使用粘贴模式,输入
:paste 把代码块粘贴进去,然后输入ctrl+d这样REPL就会把代码当做整体分析
2. 语句终止
单行写下多个语句,需要将它们用分号隔开; {}结尾不需要使用分号 if (n>0) { r=1;n=-1} 一条语句使用多行,使用操作符 告诉解析器不是语句的结尾 s = s0 + (v -v0) * t + 0.5 * (a - a0) * t * t
*scala 单行写一条语句可以不需要使用分号
3. 块表达式和赋值
在scala中,{ }块包含一系列表达式,其结果也是一个表达式。块中的最后一个表达式的值就是块的值。 val x = {val b = 2+1 ; val c = 7-1; sqrt(4) }
在scala中以赋值语句结束的块是没有值的,即Unit类型。
4. 输入和输出
输出语句 print("content") println(12) //打印后换行 printf("Hello, %s ! You are %d years old \n." ,"name" ,18) print(f"Hello, $name! In six months you will be ${age + 0.5 }%7.2f years old. \n") //变量的值,%7.2宽度为7,精度为2的浮点数格式。
输入语句
使用scala.io.StdIn的readLine方法从控制台读取一行输入,如果是要读取数字,Boolean者字符串,
可以用readInt,readDouble,readByte,readShort,readLong,readFloat,readBoolean,readChar.
readLine可以带一个参数作为提示符:
val name = readLine("Your name: ")
print("Your age: ")
val age = readInt()
println("Hello " + name + ", Next year you will be " + (age + 1) )
5. 循环
while 循环
whiel(n>0){
print("hello world")
}
for 循环
for( i <- 1 to 10 ){ //让 i 遍历右边表达式的所有值。
print("hello world")
}
遍历字符序列
var sum = 0
for ( char <- "hello" ) sum += char
6. 函数
def fac(n: Int) = { var r = 1 for(i <- 1 to n) r = r * i r }
在本例中我们不需要用到return。我们也可以像java或C++那样使用return,以立即从某个函数中退出,不过在Scala中这种做法并不常见。
***对于递归函数,我们必须指定返回类型:
def fac(n : Int): Int = if (n <=0 ) 1 else n * fac(n - 1)
如果没有返回类型,Scala编译器就无法校验n * fac(n - 1) 的类型是Int。
7. 默认参数和带名参数
在调用某些函数时并不显式的给出所有参数值,对于这些函数我们可以使用默认参数
def decoreate(str: String, left: String = "[", right: String = "]") =
left + str + right这个函数有连个参数,left和right,带有默认值 "["和"]"
调用 decorate("hello") > "[hello]"
混用未命名参数和带名参数,将未命名参数排在前面
8. 变长参数
实现一个可以接受可变长度参数列表的函数
def sum(args: Int*) = {
var result = 0
for(arg <- args) result += arg
result
}可以使用任意多的参数来调用该函数
val s = sum(1,2,3,4,5,6)
有值序列不能直接传入
val s = sum(1 to 6) //错误
val s = sum(1 to 6 : _*) //正确,将1 to 6 当做参数序列处理
9. 过程
如果函数体包含在花括号当中但没有前面的 = 号,那么返回类型就是Unit。这样的函数被称为过程(proceduce)。不返回值
def box(s : String){ //没有=号
val border = "-" * (s.length + 2)
print(f"$border")
}
等价与
def box(s : String) : Unit = {
.....
}
10. 懒值
当val被声明为lazy时,它的初始化将被推迟,直到我们首次对它取值。
val words = scala.io.Source.fromFile("/usr/bin/words") //在word被定义时即被取值
lazy val words = scala.io.Source.fromFile("/usr/bin/words") //在word被首次使用时取值
***懒值并没有额外的开销。我们每次访问懒值是,都会有一个方法被调用,而这个方法将会以线程安全的方式检查该值是否已被初始化。
11. 异常
Scala没有“受检”异常——不需要声明函数或方法可能会抛出某种异常。
throw表达式有特殊的类型nothing。这在if/else表达式中很有用。
if(x >= 0){
sqrt(x)
}else throw new IllegalArgumentException("x should not be negative")第一个分支类型是Double,第二个分支类型是nothing。因此,if/else表达式的类型是Double。
try {.....} catch {......} finally {......}