在所有fp语言中,理解选项类型和模式匹配是必不可少的。事实上,这两个特性都使fp成为面向对象语言的一个更好的替代品。使用选项类型可以避免
null
异常,使用模式匹配可以解构值。在这种情况下,可以过滤掉不存在的键,并转换
option
结果为正常值:
//create test dictionary
let map1 = [("a",1); ("b",2);("c",3)] |> Map.ofList
//list of keys, "d" doesn't exist in the dictionary/map
let keys = ["a";"b";"d"]
keys
|> List.map (fun x -> map1.[x])
//System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
keys
|> List.map (fun x -> map1.TryFind(x))
//You get back a string option list, with the last element missing as the key "d" doesn't exist
//val it : int option list = [Some 1; Some 2; None]
//Method A: filter out the none existing items
keys
|> List.map (fun x -> map1.TryFind(x))
|> List.choose id //choose will get rid of the Nones and return the actual value, not the option. id is the identity function.
//Method B: replace the None with some default value, and also get rid of the option
//Let's say you replace each non existing value with 999
keys
|> List.map (fun x -> map1.TryFind(x))
|> List.map (Option.defaultValue 999)
//val it : int list = [1; 2; 999]
//In general if necessary you can always pattern match
let myOption1 = Some "A"
let myOption2 = None
match myOption1 with
| Some x -> x //try matching whatever is in myOption1 and returns the x portion of Some x, in this case "A"
| None -> "No value"
//val it : string = "A"
match myOption2 with
| Some x -> x
| None -> "No value" //since the value of myOption2 is None, Some x won't match, None will match, and return "No value"
//val it : string = "No value"