中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

5、Scala模式匹配

發布時間:2020-07-14 08:12:19 來源:網絡 閱讀:509 作者:寬哥記事 欄目:大數據

一、case class

    用case修飾的Class 我們稱之為Case Class。編譯器看到這個case修飾的class,會為這個class加一些額外的特性:

1、編譯器會為Case Class增加一個以類名為名字的工廠方法,這個工廠方法作用是構建這個類的對象

                val v = Var("x") //構建對象的時候不需要用new關鍵詞

2、編譯器默認的為case class的值參數加上了val來進行修飾,所以這些值參數和一個類里的域一樣

                v.name

3、編譯器自動為case class添加了toString、hashCode以及equals方法。可以用 == 來比較case class,比較case class的類型以及case class中的值參數

op.right == Var("x")

4、編譯器為case class增加了一個copy方法,使得case class的值參數的值可以修改。如果一個case class中只要幾個特定的值參數需要改變的話,用copy比較方便。

                val opNew = op.copy(operator = "-")

    case 除了可以修飾class,還可以修飾object,就是表示一個單例對象

    case class最大的優點就是配合模式匹配

二、Scala的match表達式 和java switch區別

    1、Scala的match表達式可以計算出一個值,而Java的switch卻不能

    2、模式匹配的表達式永遠不會穿透到下一個case表達式中, java的switch中沒有break的話,則會穿透到下一個分支

    3、模式匹配中如果沒有任何的模式被匹配到,則拋出MatchError異常

三、SealedClass

    當你在用模式匹配的時候,你肯定需要考慮所有場景的case,有的時候我們可以用default來代替所有沒有考慮到的情況,但是有的時候這個默認值沒有意義,這個時候怎么來保證你能考慮到所有的情況呢?我們讓編譯器來幫我們考慮,我們可以在case class的父類上加一個sealed的關鍵字,這個sealed會幫我們做兩件事情:

        1:在我們定義模式匹配的時候,如果沒有考慮全場景,編譯器會報警告

        2:被sealed修飾的類,不能被在其他文件中的case class繼承

四、模式的種類

    1、通配符模式  case _        可以用于匹配默認的場景,可以用于可以忽略的對象的域的情況

    2、常量模式

            def describe(x: Any) = x match {

                case 5 => "five"

                case true => "truth"

                case "hello" => "hi!"

                case Nil => "the empty list"

                case _ => "something else"

              }

                describe(5) //res6: String = five

                describe(true) //res7: String = truth

                describe("hello") //res8: String = hi!

                describe(Nil) //res9: String = the empty list

                describe(List(1, 2, 3)) //res10: String = something else                     

    3、變量模式

            可以將被匹配的表達式的值綁定到模式中的變量中,這樣可以在expressions中使用這個變量

                val i = 1 + 1

                var result = i match {

                  case 0 => "zero"

                  case somethingElse => "not zero: " + somethingElse

                }

                println(result) // not zero: 2

            編譯器怎么判斷是常量模式還是變量模式?

                val pi = math.Pi

                result = E match {

                  case pi => "strange math? Pi = " + pi //以小寫字母開頭的單詞被編譯器認為是變量模式

                }

               result = E match {

                  case `pi` => "strange math? Pi = " + pi //以反引號擴起來的為常量模式

                  case _ => "OK"

                }

    4、構造器模式。支持深度匹配   

    5、序列模式。支持固定長度的序列或者數組,也支持非固定長度。

                v match {

                      case List(0, _*) => println("list it")//匹配含有任意個元素的List,并且第一個元素等于0

                      case Array(0, _*) => println("array it")//匹配含有任意個元素的Array,并且第一個元素等于0

                      case _ =>

                    }

    6、元組模式

             def tupleDemo(expr: Any) = expr match {

                case (a, b, c) => println("matched " + a + b + c)

                case _ =>

              }

7、類型模式

        def generalSizeWithPattern(x: Any) = x match {

              case s: String => s.length

              case m: Map[Int, Int] => m.size

              case _ => -1

            }

        關于類型擦除,數組是個例外,因為數組在java中是特殊處理了,在scala中也是特殊處理了,在jvm中對應著不同類型的數組,比如int[], float[]等

            isIntIntMap(Map(1 -> 1)) //true

            isIntIntMap(Map("abc" -> "abc")) //true

        

            isStringArray(Array("abc")) //yes

            isStringArray(Array(1, 2, 3)) //no

8、變量綁定

        val expr = UnOp("abs", UnOp("abs", Var("x")))

        expr match {

          case UnOp("abs", e@UnOp("abs", i@Var(_))) => println(e + " " + i)

          case _ =>

        }

五、模式守衛

    在模式中可以定義條件。

    def simplifyAdd(e: Expr) = e match {

    case BinOp("+", a, b) if a == b => BinOp("*", b, Number(2))

    case _ => e

   }

六、模式重疊

    盡量避免模式重疊    

    def simplifyBad(expr: Expr): Expr = expr match {

        case UnOp("-", UnOp("-", e)) => e   //第一個case

        case UnOp(op, e) => UnOp(op, simplifyBad(e))  //第二個case

      }

    當case1屬于case2的子集,那么case1可以放在case2之前,若放在case2之后,則永遠無法執行,編譯器會報警告unreachable code.

七、Option

    Option視作一個容器,可以有東西,也可以沒有東西。Some 表示有且僅有一個東西 None表示沒有東西

    val opt = Some("aaa")

    opt.getOrElse("default")

    

     在模式匹配中使用:

    val capitals =

          Map("France" -> "Paris", "Japan" -> "Tokyo")

    def show(x: Option[String]) = x match {

        case Some(s) => s

        case None => "?"

      }

    show(capitals get "Japan") //res25: String = Tokyo

    show(capitals get "France") //res26: String = Paris

    show(capitals get "North Pole") //res27: String = ?


八、模式在變量定義中的使用

    val myTuple = (123, "abc")

    val (number, string) = myTuple


    val exp = new BinOp("*", Number(5), Number(1))

    val BinOp(op, left, right) = exp

九、模式在偏函數中使用

    1、一個case序列作為全函數(complete function)

        val withDefault: Option[Int] => Int = {

          case Some(x) => x

          case None => 0

        }

    2、如果缺少了一個case會出現什么情況呢?編譯會出現警告

        val second: Option[Int] => Int = {

          case Some(x) => x

        }

     3、如果我們的case列表是部分的場景,我們需要告訴編譯器這是一個偏函數(partial function)

        val partial : PartialFunction[Option[Int], Int] = {

          case Some(x) => x

        }

    4、我們盡可能的用全函數,因為偏函數如果沒有考慮清楚需要處理的case的話,可能會拋異常。

    上面的partial就是和下面的p是一個意思

         val p =  new PartialFunction[Option[Int], Int] {

          override def isDefinedAt(x: Option[Int]) = x match {

            case Some(_) => true

            case None => false

          }

    

          override def apply(v1: Option[Int]) = v1 match {

            case Some(x) => x

          }

    

    5、如果要使用偏函數,推薦用下面模式

        if (partial.isDefinedAt(None)) {

          partial(None) //如果單獨運行的話,還是會拋異常

        }

十、模式在for中使用

    val results = List(Some("apple"), None, Some("orange"))

    for (Some(fruit) <- results) println(fruit)


    val capitals =

      Map("France" -> "Paris", "Japan" -> "Tokyo")

    for ((country, city) <- capitals)

      println("The capital of " + country + " is " + city)

十一、萃取器unapply

    含有成員方法unapply的object,我們稱之為extractors(萃取器)。extractors可以同時定義apply(可選的)和unapply方法。

    

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宣化县| 吉木萨尔县| 灵石县| 会昌县| 贞丰县| 武定县| 佛冈县| 莱阳市| 乌拉特中旗| 万年县| 罗城| 阳朔县| 鹿邑县| 双城市| 贡嘎县| 抚顺市| 聂拉木县| 昆山市| 钟山县| 衡水市| 句容市| 宜昌市| 汝南县| 太白县| 治多县| 林芝县| 三台县| 长宁县| 江永县| 乐安县| 镶黄旗| 木兰县| 宕昌县| 勐海县| 镇平县| 武平县| 正镶白旗| 通州区| 贡觉县| 金坛市| 达尔|