一起学scala--控制结构和函数
条件表达式
与java/c++不同的是,scala中 if / else语法是有返回值的,这个值就是跟在if / else 之后的最后一个表达式的值。
val s:String = if(1 > 0) "yes" else "no"
// 返回值是if/else表达式返回值的公共超类型,这里是String。
val value: Any = if (1 > 0) "yes" else 1
// 如果else没有返回值,默认就为Unit类型,相当于java中的void,用()表示。
val value: Any = if (1 > 0) "yes" else ()
块表达式和赋值
在scala中,块表达式也是有值的,这个值就是块中的最后一个表达式的值。赋值语句的值为Unit类型。
val distance: Double = {
val a = 2
val b = 4
scala.math.sqrt(a * a + b * b)
}
输入输出
在scala.io.StdIn类下包含输入的各种方法。
val in: StdIn.type = scala.io.StdIn
val n: Int = in.readInt()
val bool: Boolean = in.readBoolean()
val d: Double = in.readDouble()
val str: String = in.readLine()
//格式化输入
val in: StdIn.type = scala.io.StdIn
val list: List[Any] = in.readf("this is {0,number,integer}")
// 输入this is 1.22 输出 1
如果要打印一个值,我们用print或println函数,后者会追加一个换行符。
scala中的字符串插值有三种。
- f:带格式化命令,类似其他语言的printf函数。
- s:不带格式化命令,常用。
- raw:转义序列不会被求值。
val name = "yoleen"
val age = 10
print(s"My name is $name and I am ${age*2} years old\n")
//My name is yoleen and I am 20 years old
print(f"My name is $name%s and I am ${age*2.5}%.2f years old\n")
//My name is yoleen and I am 25.00 years old
print(raw"My name is $name and I am ${age*2.5} years old\n")
//My name is yoleen and I am 25.0 years old\n
循环
scala有与java和c++相同的while和do循环。例如:
while(n>0){
r *= n
n-=1 //没有-- 和 ++ 操作符
}
在scala中for循环是这样的:
// for 的语法结构
for(elem <- 表达式){
//elem为什么值取决于表达式里面的值。
}
for(i <- 1 to 10){
// RichInt类中的to方法,返回1 to n(包含n)的Range区间
n += i
}
for(elem <- "hello"){
//elem = 'h'...'o'
}
//接Boolean表达式
for(i <- 1 to 10 if(i%2==0)){
print(f"$i%3d")
}//将交出2 4 6 8 10
//多重循环 九九乘法表
for(i <- 1 to 9; j <- 1 to i){
print(s"$i*$j=${i*j} ")
if(i==j){
println //没参省略括号
}
}
//for推导式,使用yield生成一个长度不可变的数组
//注意for后面没有{}
val ints: immutable.IndexedSeq[Int] = for (i <- 1 to 9; j <- 1 to i) yield {
i*j
}
函数
要定义函数,你需要给出函数的名称、参数和函数体,例如:
def main(args: Array[String])= {}
你必须要给出所有参数的类型,不过,只要不是递归函数,你可以不指定函数的返回类型。scala编译器能通过返回值推断出返回类型。
对于递归函数我们必须要指定返回类型,例如:
// 递归求字符串中的所有字符的乘积。
def recursive(s:String,i:Int):Long={
if(i<s.length){
recursive(s,i+1)*s(i).toInt
}else{
1
}
}
默认参数和带名参数
在函数定义时可以带上初始值。如:
def sayHello(name:String,s:String="hello,",left:String="[",right:String="]")={
s+left+name+right
}//输入name="yoleen" 将输出 hello,[yoleen]
对于参数较多的函数,带名参数能显得程序更加易读。
注意参数并不需要跟参数列表顺序一致。
sayHello(s="Hi,",name="yoleen",right="]!")
//将输出 Hi,[yoleen]!
可变长参数
有时候你并不知道输入多少个参数,此时你可以使用可变长参数。
//args是一个类型为seq的参数。
def sum(args:Int*)={
var result = 0
for(elem <- args){
result+=elem
}
result
}
虽然args是一个序列,但这种写法是错误的。
val s = sum(1 to 5) //报错
我们不能将一个序列中的元素当做变长参数直接传递给方法,解决方法就是,将其当作参数序列进行处理,在序列后面追加 :_* 例如:
val s = sum(1 to 5:_*) //返回15
lazy
当val被声明为lazy时,它的初始化将被延迟,直到我们首次对它取值。例如:
lazy val file = scala.io.Source.fromFile("文件路径")
//在定义变量为lazy后,只有我们第一次使用这个变量时,file才会被赋值。
//在初始化开销较大的程序中,lazy十分有用。
//注意:lazy并非没有额外开销,我们每次访问lazy变量时,
//会有一个函数已线程安全的方式检查lazy变量有没有被初始化。
码字不易,如果觉得文章不错,麻烦点下推荐。