1. 程式人生 > >Scala的控制結構和函式

Scala的控制結構和函式

控制結構和函式

先看以下簡單的一個條件表示式的demo

object TestConditional {

  def main(args: Array[String]): Unit = {
    // scala的if判斷表示式
    var x = 1
    if (x > 0) x = 10 else x = 20
    println(x)
  }
}

Scala的if/else語法結構與java一樣,如以上程式碼一樣,需要注意的是當else部分缺失了比如:if(x>0) 1,這個if語句沒有輸出值,但是在Scala中,每個表示式都應該有值,這個問題可以引入一個Unit類,寫做()。不帶else的這個if語句等同於 if (x>0) 1 else () Scala中沒有switch語句,只需if即可解決所有。
- 語句終止

在java和C++中,每一個語句都以分號結束,而在Scala中和JavaScript類似--行尾的位置不需要分號,因為Scala編譯器能夠從上下文明確判斷出是語句的終止,但是若要在單行中寫下多個語句,需要用分號隔開,例如下面的表示式需要分號隔開
if (n > 0) {r = r * n; n-=1}
若是在寫較長的語句,需要兩行來寫,需要告訴編譯器不是語句結尾,例子如下:
x = y + (v - m) * d + // +告訴編譯器不是結尾
0.5 * (c - v) * t
  • 塊表示式和賦值
在java中,塊語句是一個包含與{}中的語句序列,在Scala中{}包含一系列表示式,在Scala中,賦值動作本身沒有值,它們是Unit型別,相當於java中的void,而這個型別只有一個值,寫做()
{r = r * n; n-=1
}
  • 輸入和輸出
列印一個值可以使用print或者println函式,
例如: println("x="+"10"),另外還有一個帶有C風格格式化的字串printf函式例如:
printf("hello, %S! welcome to Scala world.\n","michael")
也可以使用readLine函式從控制檯讀取一行輸入,讀取數字,Boolean或者是字元,可以永readInt,readDouble,readByte,readShort,readLong,readFloat,readBoolean或者readChar。
// 使用readLine
val name=read
Line("your name:") print("your age") val age = readInt() printf("hello,%s! you have %d year work experience",name,age)
  • 迴圈

Scala中沒有與for(初始化變數值;變數布林表示式;變數更新),Scala中有兩個選擇:一個是使用while迴圈,而是使用以下for語句
for (i<- 表示式)讓變數i遍歷<-右邊的表示式的所有值,對於Scala集合比如Range而言,會取到集合中的每個值

Scala中沒有提供break或者continue語句退出迴圈,一般可以有以下三種方法跳出迴圈:
1. 使用Boolean型的控制變數
2. 使用巢狀函式---使用return
3. 使用breaks物件中的break方法
import scala.util.control.Breaks._
breakable {
    for(...) {
    // 退出迴圈
        if(...) break;
    }
}
  • for迴圈推導式

Scala中的for迴圈比java要豐富的多,下面介紹其高階特性

    // 多個生成器
    for (i <- 1 to 3; j <- 1 to 3) print((10 * i + j) + " ")
    println()
    // 守衛生成器,if前沒有分號
    for (i <- 1 to 3; j <- 1 to 3 if i != j) print((10 * i + j) + " ")
    // 可以定義變數,在迴圈中引入
    println()
    for (i <- 1 to 3; from = 4 - i; j <- from to 3) print((10 * i + j) + " ")

 for迴圈中的 yield 會把當前的元素記下來,儲存在集合中,迴圈結束後將返回該集合。Scala中for迴圈是有返回值的。如果被迴圈的是Map,返回的就是Map,被迴圈的是List,返回的就是List,以此類推。

scala> for (i <- 1 to 5) yield i
res10: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5) 
  • 函式

Scala中定義函式需要定義函式的名稱、引數和函式體

 def abs (x: Double) = if (x >= 0) x else -x

 必須給出所有引數的型別,只要不是遞迴就不需指定返回型別。Scala會自動通過=符號右側的表示式的型別推斷出返回型別

// 遞迴函式,必須指定返回型別
def fac(n : Int) :Int = if (n<=0) 1 else n* fac(n -1) 
  • 預設引數和帶名引數
/**
 * 我們在呼叫某些函式無需顯示給出所有的引數值,可以初始化給出預設值
 */
 def haha(str:String,left:String="[",right:String="]") = left + str +right
  • 可變引數
// 傳入的引數是單個引數
def sum(args : Int*):Int = {
    var result = 0
    for (arg <- args) result += arg
    // 返回result
    result
}

// 計算1+2的值
val s1 = sum(1, 2)
// 用法是錯誤的,因為1 to 3 是一個整數區間不是單個整數
val s3 = sum (1 to 3)
// 計算1+2+3的值(解決區間問題)
val s2 = sum(1 to 3: _*)
  • 異常處理
Scala異常的工作機制和java或C++一樣,當你丟擲異常時:
throw new IllegalArgumentException("description for exception")
和java一樣,丟擲的物件必須是java.lang.Throwable的子類,不過沒有編譯時候的檢查異常
try {
    process(new URL("http:wwww.baidu.com"))
} catch {
    // 自定義異常描述
    case _:URLException => println("bad url")
    // 使用預設異常資訊
    case ex: IOException => ex.printStackTrace()
}

使用try finally語句:
var in = new URL("http:www.baidu.com").openStream()
try {
    process(in)
} finally {
    in.close()
}