模式匹配第二彈 元組,range 和型別

2021-09-19 09:03:36 字數 3989 閱讀 5803

在 swift 當中,switch並不像 objc 一樣只能對整型或列舉進行匹配。

事實上,我們可以使用switch對很多態別進行匹配,包括(但不僅限於)元組。

let point = cgpoint(x: 7, y: 0)

switch (point.x, point.y)

還有一點要注意的是,switch是按case模式被指定的順序來判斷求值的,並且它會在匹配到第乙個滿足的case後跳出。與 c 和 objective-c 不同,我們不需要使用break關鍵字1。

這意味著在上面的**中,如果座標是(0, 0),則它會匹配第乙個case列印出"on the origin!",並就此打住,就算(0, _)(_, 0)也符合匹配的條件,它也不會再去進行匹配。因為它已經在第乙個匹配之後跳出了。

為什麼要止步於元組呢?在 swift 當中,我們也可以使用switch來對很多原生型別進行匹配,包括字串和字元,比如:

let car: character = "j"

switch car

可以注意到,我們可以使用按逗號分隔的多個模式來進行匹配,使符合這些模式的匹配(這裡是匹配所有的母音字母)都執行同一段**。這可以避免我們寫很多重複的**。

range 在模式匹配中也很有用。提醒一下,range是乙個泛型型別,它包含了t型別的startend成員,同時t必須是乙個forwardindextype。這包括intcharacter在內的許多態別。

?我們可以使用range(start: 1900, end: 2000)來顯式地宣告乙個 range,也可以使用語法糖操作符..<(不包含最後乙個數end)或...(包含最後乙個數end),所以我們也可以將上面的 range 寫為1900..<2000(更方便也更易讀)

那麼我們如何在switch當中使用它們呢?其實相當簡單,在case模式中使用 range 來判斷值是否落於這個範圍內!

let count = 7

switch count

可以看到我們在case當中混用了int整型值與range的值。這樣的使用並沒有任何問題,只要我們保證覆蓋了所有可能的情況。

雖說int是最常用的 range 型別,我們也可以使用其它的forwardindextype型別,包括...character!還記得上面寫的**麼?它有一點問題,那就是對於標點符號以及其它不是a-z的字元,它也會列印出 "consonant"。讓我們來解決這個問題2(同時也增加了小寫字母):

func chartype(car: character) -> string 

}print("jules verne".characters.map(chartype))

// ["consonant", "vowel", "consonant", "vowel", "consonant", "other", "consonant", "vowel", "consonant", "consonant", "vowel"]

至此一切順利,但我們能不能更進一步呢?答案是當然沒問題:讓我們把模式匹配用在... 型別上!

在這裡,我們定義了三個結構體,並遵守相同的協議:

protocol medium 

}struct book: medium

struct movie: medium

struct website: medium

// and an array of media to switch onto

let media: [medium] = [

book(title: "20,000 leagues under the sea", author: "jules vernes", year: 1870),

movie(title: "20,000 leagues under the sea", director: "richard fleischer", year: 1955)

]

然後我們要如何對medium使用switch的模式匹配,讓它對bookmovie做不同的事呢?簡單,在模式匹配中使用asis

for medium in media 

}

注意到對bookmovie使用的as,我們需要確定它們是不是特定的型別,如果是,則將它們轉換後的型別賦值給乙個常量(let blet m),因為我們之後要使用到這個常量3。

而另一方面,對website我們只使用了is,因為我們只需要檢查medium是不是乙個website型別,如果是,我們並沒有對它進行轉換與儲存在常量中(我們不需要在print語句中使用到它)。這與使用case let _as website有點類似,因為我們只關心它是不是website型別,而不需要它的物件的值。

?注意:如果必須在swtich匹配中使用到asis,這裡有可能存在**異味,比如,在上面這個特定的例子中,在protocol medium當中新增乙個releaseinfo: string屬性就比使用switch來對不同的型別進行匹配要好。

在接下來的部分,我們會學習如何建立可以直接使用於模式匹配的自定義型別,探索更多的語法糖,並看到如何在switch語句之外使用模式匹配,以及更加複雜的匹配表示式... 迫不及待了吧!

可以使用fallthrough關鍵字來讓求值判斷流向下乙個case。但是在實踐上要使用到這個關鍵字的場景很少,並不經常會碰到。

當然,這種字串的分析方法並不是最好的,也不是值得推薦的 —— 因為 unicode 字元以及本地化都比這複雜得多。所以類似這樣的功能我們更應該使用nscharacterset,考慮當前的nslocale把哪些字母定義為母音(「y」 是母音嗎?還有 「õ」 or 「ø」 呢?),等等。不要把這個例子看得太認真,我只是用它來展示switch+range的強大而已。

儘管與if let b = medium as? book表示式很相似 —— 當medium可以被轉換為特定型別的時候,它們都將其繫結到乙個變數上 —— 但是在模式匹配中我們要使用as而非as?。儘管它們的機制很相似,但是它們的語義是不同的(「嘗試進行型別轉換,如果失敗就返回nil」 vs 「判斷這個模式是不是匹配這種型別」)。

第二彈 getch getchar和gets

緩衝輸入函式,函式只有在滿足輸入次數要求的前提下,遇到回車時才結束輸入,之前所有的字元都會逐個顯示在螢幕上,但是只有第乙個字元返回乙個ascii碼。具體的過程就是getchar 被呼叫時,程式就等著使用者按鍵,且將使用者輸入的字元依次回顯到螢幕,使用者必須摁完規定的次數 迴圈語句 即使是回車也要摁 ...

PHP高階(第二彈 類和物件)

類是物件導向程式設計的基本概念,php中也有類和物件的概念。比如定義乙個汽車類 定義乙個類 class car 受保護的屬性與私有屬性不允許外部呼叫,在類的成員方法內部是可以呼叫的。public function getprice 物件通過new關鍵字進行例項化 car new car 也可以採用變...

C Light 和 uLua的對比第二彈

上次的對比大家還有印象否,c light和ulua對比各有勝負 今天我們加入乙個去反射優化,這是ulua沒辦法實現的優化,我們也就只能不要臉的勝之不武了 以原生執行同一測試時間為x1,數字越小的越快 專案ulua c light c light 去反射優化 效能測試一 x4.5 x4.5 x2.19...