Scala--控制结构和函数

  本篇博客,将介绍scala的:

  1. 条件表达式
  2. 循环
  3. 函数
  • 主要是对这些表达式语句结构的熟悉,需要多练习。在scala中表达式(3+4)和语句(if语句)是不同的概念,表达式有值,语句执行动作
  • 记住,scala几乎所有构造出来的语法结构都有值。

条件表达式

  • if/else的表达式语法和java类似,只是需要注意的是:
  1. if/else有返回值
  2. scala代码结尾不需要“;”,除非一行要写多条语句,这个和Python类似。下例打印出了if的返回值1,这个小例子就充分说明了if语句是有返回值的。
    1
    2
    3
    4
    5
    6
    7
    8
    scala> val isTrue=true
    isTrue: Boolean = true

    scala> if(isTrue) 1 else 0 ##返回值
    res0: Int = 1

    scala> val f = if(isTrue) 1 else 0 ##返回值
    f: Int = 1
  • if/else表达式的类型推断,取两个类型的公共父类型,如下String和Int,则表达式的值是Any
    1
    2
    scala> val f = if(isTrue) "this reture true" else 0
    f: Any = this reture true

块语句

  • 在scala中“{}”包含的一系列表达式,叫做块语句,块中最后一个表达式的值就是块的值,即块的返回值。下面,定义一个块语句,执行后返回了变量ss的值,ss的值就是块语句中最后一个表达式的值。
    1
    2
    scala> val ss = { val s1=78; val s2=s1*0.8; s1+s2 }
    ss: Double = 140.4

while循环

  • while循环,和java的while和do循环相同,这里就不过多讲解了,实例如下图所示。我们定义了一个var变量,然后通过while循环打印出结果,注意scala不支持n++,n- -

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    scala> :paste
    // Entering paste mode (ctrl-D to finish)

    var n =3
    while( n > 0 ) {
    n-=1
    println(n)
    }

    // Exiting paste mode, now interpreting.

    2
    1
    0
    n: Int = 0
  • 注:在”Repl”中写多行代码的时候,每写一行敲一下“回车键”然后它会自动去识别程序是否结束,直到你真正的写完代码,有时候不是很方便;
    还有一种粘贴的方法,输入:paste然后就可以随意的写代码了,写完后Ctrl+D退出并运行代码,如上图所示。

for循环

for基础

  • 语句结构

    for( i <- 表达式 ) #让变量i遍历<-右边的表达式的所有值,i具体执行取决于表达式
      循环体

  • 示例1,for循环中的to:to:包含上线区间。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    scala> var n = 10; for(i <- 1 to n) println(i)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    n: Int = 10
  • 示例2,for循环中的untiluntil:返回一个并不包含上线的区间。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> var n = 10; for(i <- 1 until n) println(i)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    n: Int = 10
  • 示例3,不使用to和until

    1
    2
    scala> for(s <- "blog.xiaoxiaomo.com") print(s+" ")
    b l o g . x i a o x i a o m o . c o m

for跳出语句

  • scala中没有breakcontinue来退出循环,我们可以这样操作

    1. 使用Boolean的变量控制。
    2. 使用嵌套函数,可以从函数当中return。
    3. 使用Breaks对象的break方法。
  • eg:

    1
    2
    3
    4
    5
    breakable{
    for (...) {
    if(...) break ;//#退出breakable块
    }
    }

for进阶

  1. 在for循环“()”中可以使用多个生成器, 用“;”隔开;
  2. 并且每一个生成器都可以带一个守卫if开头的Boolean表达式);
  3. for推导式,如下示例:
  • 示例1,多个生成器,即多层循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    scala> :paste
    // Entering paste mode (ctrl-D to finish)

    for(i <- 1 to 9; j <- 1 to 9) {
    if(j == 9) {
    println(i * j)
    } else {
    print(i * j + " ")
    }
    }

    // Exiting paste mode, now interpreting.

    1 2 3 4 5 6 7 8 9
    2 4 6 8 10 12 14 16 18
    3 6 9 12 15 18 21 24 27
    4 8 12 16 20 24 28 32 36
    5 10 15 20 25 30 35 40 45
    6 12 18 24 30 36 42 48 54
    7 14 21 28 35 42 49 56 63
    8 16 24 32 40 48 56 64 72
    9 18 27 36 45 54 63 72 81
  • 示例2,for循环守卫

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> for(i <- 1 to 20 if i % 2 == 0) println(i)
    2
    4
    6
    8
    10
    12
    14
    16
    18
    20
  • for推导式:如果for循环的循环体以yield开始,该循环就会构造出一个集合,每次迭代就生成一个集合的值。

    1
    2
    scala> for( i <- 2 to 8 ) yield i%2
    res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 0, 1, 0, 1, 0)

函数

基本语法

  • 语法如图:

图来源于:《Scala编程》

  1. 函数必须指定参数的类型
  2. 函数只要不是递归的就不需要指定返回值类型(因为无法推断出递归函数的类型)。
  3. 在函数中,不需要使用return。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> def max( x:Int, y:Int ) : Int ={
    | if(x>y) x
    | else y
    | }
    max: (x: Int, y: Int)Int

    scala> max(78,88)
    res8: Int = 88

    scala> max(18,99)
    res10: Int = 99

函数参数

在函数中,我们可以使用默认参数。函数调用时:

1、如果没用给出所有参数,函数会使用默认参数(后面不够的参数使用默认值)。
2、也可以指定参数名,参数名不需要按顺序排列。
3、如果混合使用(未名参数和带名参数),只要未名参数排在前面即可。

1
2
3
4
5
6
7
8
9
scala> def defStr( left:String = "[" , str:String , right:String = "]" ) = {
| print( left + str + right )
| }
defStr: (left: String, str: String, right: String)Unit

scala> defStr("[","Hi")
[Hi]
scala> defStr(left="<",right=">",str="xiaoxiaomo")
<xiaoxiaomo>

4、变长参数,可以接受多个参数

1
2
3
4
5
def sum(args:Int*) = {
var result = 0 ;
for(arg <- args) result+=arg
result
}

调用函数,sum(3,4,6,23,3),函数得到的是一个Seq类型的参数,注意调用函数是传入的参数不能是一个区间,eg:
sum(2 to 9)是不可以的,应该为sum(2 to 9:_*);

过程

  • 在scala中,如果函数没有返回值,那么该返回值类型我们可以用Unit来表示,这种没有返回值的函数我们称之为过程

    1
    2
    3
    4
    5
    6
    7
    scala> def pr(s:String){
    | print(s)
    | }
    pr: (s: String)Unit

    scala> pr("小小默")
    小小默
  • 上面省略了Unit,由于没有返回值也可以省略“=”号,下面语句相同:

    1
    2
    3
    4
    5
    6
    7
    scala> def pr(s:String) : Unit = {
    | print(s)
    | }
    pr: (s: String)Unit

    scala> pr("小小默")
    小小默

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器