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

控制結構和函式

在Scala中 ,幾乎所有語法結構都有值

If else

在這裡插入圖片描述
s為什麼有值?
If 語句的返回型別取決於最後一條語句。
語句後面的分號不是必須的
Scala 沒有三元運算子,不需要,if else替代了三元運算子

If 表示式會有一個返回值型別,如果 if 或者 else 返回的型別不一樣,就
返回 Any 型別(所有型別的公共超型別)
在這裡插入圖片描述
如果缺少一個判斷,什麼都沒有返回,但是 Scala 認為任何表示式都會
有值,對於空值,使用 Unit 類,寫做()【叫做無有用佔位符,相當於 java中的 void】
在這裡插入圖片描述
注 :行尾的位置不需要分號,只要能夠從上下文判斷出語句的終止即可。但是如果在單行中寫多個語句,則需要分號分割 。在Scala 中, {}塊,其結果也是一個表示式。塊中最後一個表示式的值就是塊的值。

While表示式

Scala 提供和 Java 一樣的 while 和 do 迴圈,與 If 語句不同,While 語句
本身沒有值,即整個 While 語句的結果是 Unit 型別的()。

while (n > 0) {
r = r * n
n -= 1
println (r)
}
do{
r = r * n
n -= 1
println (r)
} while(n > 0)

注: scala並沒有提供break和contine語句來退出迴圈,如果退出使用

1.使用Boolean型的控制變數
2. 使用巢狀函式,從函式中return
3. 使用Break物件的break方法

import scala.util.control.Breaks._ //手動引入
object Break {
  def main(args: Array[String]): Unit = {
    var r = 1
    var n = 10

    breakable{		//傳遞值
      while(n > 0){
        r = r *n
        n -= 1
        println(n)
        if (n == 5) break //
      }
    }
  }
}

for表示式

Scala 也為 for 迴圈這一常見的控制結構提供了非常多的特性,這些 for
迴圈的特性被稱為 for 推導式(for comprehension)或 for 表示式(for
expression)

推導式一詞起源於函數語言程式設計:

for (i <- -1 to 3; j <- 1 to 3) println(i+" "+j+" ")

像變數名 <- 集合 這樣的表示式被稱為生成器表示式,會基於集合生成單獨的數值

保護式:也叫守衛,可以新增一個或者多個守衛,不需要continue語句

 for (i <- 1 to 3;j<- 1 to 3 if i != j)println(i+" "+j)

for推導式可以引入變數

for (i <- 1 to 3; from = 4 -i)println( from +" ")

需要返回值怎麼辦?

使用yield關鍵字在for表示式中生成新的集合,for-yield表示式所生成的集合型別將根據所遍歷的集合型別推導而出

  val result = for( i <- 1 to 10)yield i %3
    println(result)

{}和()對於 for 表示式來說都可以,for 推導式有一個不成文的約定:當
for 推導式僅包含單一表達式時使用原括號,當其包含多個表示式時使用大括號。值得注意的是,使用原括號時,早前版本的 Scala 要求表示式之間必須使用分號

函式

java中一般通過靜態方法模擬
函式的定義

def 函式名(引數名 : 型別)[: 返回型別] = 函式體

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

遞迴函式
def res(n:Int) : Int = if(n <= 0) 1 else n*res(n -1 )
遞迴函式必須有返回值,且指定函式返回值型別

函式引數預設值
引數型別後面設定預設值

   def decotate(str:String,left: String ="[",right: String = "]") = left + str + right
    //未設定引數,預設[]
    println(decotate("hello"))
    //設定引數 
    println(decotate("hello","<<<",">>>"))

函式的命名引數
不按照原先函式的引數順序,指定引數順序

println(decotate(left = "<<<",right = ">>>",str = "你好"))

變長函式

  def sum(args : Int*): Int ={
      var result = 0
      for (arg <- args) result += arg
      result
    }

    println(sum(1,4,5,6))

需要指定返回型別,否則結果會被捨棄

*_告訴編譯器 1 to 5 當做引數序列處理 Range

  println(sum(3 to 6 : _*))

head 和 tail

head是第一個元素,tail是剩下的元素的集合

def reds(qarg: Int*) : Int ={
      if (qarg.length == 0) 0
      else qarg.head + reds(qarg.tail : _*)
    }

    println(reds(4,2,4,59,76))

注:

  1. Scala可以通過=右邊表示式,推斷出函式的返回型別,如果函式體需要多個表示式,可以用程式碼塊{}
    2.可以將return當做函式版本的break語句
  2. 遞迴函式一定要指定返回型別
  3. 變長引數通過*來指定,所有引數會轉換為一個序列
  4. _* 告訴編譯器,Range當做引數序列化處理
  5. Head是獲取首元素,tail是獲取剩下元素的序列

過程:

沒有返回值的函式:返回型別是unit,沒有 = 號

def box(s : String) {  // Look carefully: no =
val border = " "- - " * s.length + " " --\ \n n" "
println(" "\ \n n " + border +  "|" + s +  "|\ \n n " + border)
}

懶值

當val被宣告為lazy時,初始化將會被延遲,直到我們對此首次取值

使用事項:

  1. 用於初始化開銷比較大的語句
  2. 解決迴圈依賴問題 A依賴B B依賴A
  3. 是開發懶資料結構的基礎
 def lazyed() {
      lazy val property = init();//沒有使用lazy修飾
      println("after init()")
      println(property)
    }

異常

當碰到異常情況時,方法丟擲一個異常,終止方法本身執行,異常傳遞給其呼叫者,呼叫者可以處理該異常,也可以升級到它的呼叫者,執行系統會一直這樣升級異常,直到呼叫者處理,如果沒有處理,終止程式

Scala的異常工作機制和java一樣,但是Scala沒有受檢異常,不需要宣告函式或者方法可能丟擲某種異常,受檢異常在編譯器被檢查,java必須宣告方法所會丟擲的異常型別

丟擲異常: 用throw關鍵字,丟擲一個異常物件,所有的異常都是Trowable的子型別,throw表示式都是有型別的,為Nothing,因為Nothing是所有型別的子型別,所以throw表示式可以用在需要型別的地方

//並不像 Java 程式碼那樣,需要宣告方法會丟擲異常,這給程式設計師省去理論很多煩惱。方法上也不需要宣告
def divide(x: Int, y: Int): Int = {
if (y == 0) throw new Exception("Divide by zero")
else x / y
}

捕捉異常
在 Scala 裡,借用了模式匹配的思想來做異常的匹配,因此,在 catch 的
程式碼裡,是一系列 case 字句。

異常捕捉的機制與其他語言中一樣,如果有異常發生,catch 字句是按次
序捕捉的。因此,在 catch 字句中,越具體的異常越要靠前,越普遍的異常越靠後。 如果丟擲的異常不在 catch 字句中,該異常則無法處理,會被升級到呼叫者處。

異常捕獲通常採用模式匹配的語法:

try {
process(in)
}  catch {
case ex: IOException => println(ex)
}  finally {
in.close()
}

finally 字句用於執行不管是正常處理還是有異常發生時都需要執行的步
驟,一般用於物件的清理工作。

注:

  1. Throw的型別為Nothing,存在exception的if語句型別返回型別

異常程式碼練習

     def root(x : Double) = if (x>0){sqrt(x)}else throw new IllegalArgumentException(" s" +
      " should not be negative ")
    try{
      println(root(4))
      println(root(-5))
    }catch {
      case e: Exception => println(e)
    }finally {
      println(" finally .... ")
    }