一起学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变量有没有被初始化。

码字不易,如果觉得文章不错,麻烦点下推荐。

posted @ 2020-05-19 18:20  yoleen  阅读(322)  评论(0编辑  收藏  举报