在 F# 中,list是不可變的集合,包含零個或多個值。陣列中的值都必須具有相同的型別。由於陣列不可變,一旦建立陣列,其值就永遠不會改變。任何看似會修改陣列的函式或運算子(例如加入元素),實際上都會回傳新的陣列。
陣列可以如下定義:
let empty = []
let singleValue = [5]
let threeValues = ["a"; "b"; "c"]
將元素加入陣列最常見的方式,是使用 ::(cons)運算子:
let twoToFour = [2; 3; 4]
let oneToFour = 1 :: twoToFour
// => [1; 2; 3; 4]
F# 陣列有一個 頭部(第一個元素)和一個 尾部(第一個元素之後的所有內容)。陣列的尾部本身也是陣列。
陣列可以透過 List 模組中定義的函式和運算子來操作,也可以使用 list 和 cons 模式手動進行模式比對:
let describe list =
match list with
| [] -> "Empty list"
| head::tail -> sprintf "Non-empty list with head: %d" head
describe [] // => "Empty list"
describe [1] // => "Non-empty with head: 1"
describe [5; 7; 9] // => "Non-empty with head: 5"
你也可以在模式比對時 捨棄 某個值;當你在特定情況中 不在意 某個值(也就是你不打算 使用 它)時,可以使用底線('_')來表示這點:
let describe list =
match list with
| [] -> "Empty list"
| [x] -> "List with one item"
| [_; y] -> "List with two items (first item ignored)"
| _ -> "List with many items (all items ignored)"
describe [] // => "Empty list"
describe [1] // => "List with one item"
describe [5; 7] // => "List with two items (first item ignored)"
describe [5; 7; 9] // => "List with many items (all items ignored)"
在模式比對時,單獨的 '_'應該總是最後出現;任何不符合其他情況的值,都會由這個情況處理。
在這個練習中,你將撰寫程式碼,記錄你想在 Exercism 上學習的程式語言陣列。
一共有六個任務,全都會涉及處理陣列。
為了記錄你想學習的程式語言,你需要建立一個新的陣列。定義 newList 繫結,讓它包含一個全新的空陣列。
newList
// => []
目前你手上有張紙,上面列出你想學習的程式語言:F#、Clojure 和 Haskell。定義 existingList 繫結來代表這個陣列。
existingList
// => ["F#"; "Clojure"; "Haskell"]
當你在 Exercism 上探索、發現更多有趣的程式語言時,你會想把它們加進陣列裡。實作 addLanguage 函式,把新的程式語言加到陣列開頭。
addLanguage "TypeScript" ["JavaScript"; "CoffeeScript"]
// => ["TypeScript"; "JavaScript"; "CoffeeScript"]
一個一個數程式語言很不方便。實作 countLanguages 函式,計算陣列裡有多少個程式語言。
countLanguages ["C#"; "Racket"; "Rust"; "Ruby"]
// => 4
某個時刻,你發現你的陣列其實是反著排的!實作 reverseList 函式來反轉你的陣列。
reverseList ["Prolog"; "C"; "Idris"; "Assembly"]
// => ["Assembly"; "Idris"; "C"; "Prolog"]
雖然你熱愛所有程式語言,但 F# 在你心中有個特別的位置。因此,只要符合以下情況,你就會對一個程式語言的陣列感到非常興奮:
實作 excitingList 函式,檢查一個程式語言的陣列是否令人興奮:
excitingList ["Nim"; "F#"]
// => true