How can I implement the same behavior as Dictionary.TryGetValue
So, given then following code
type MyClass () =
let items = Dictionary<string,int>()
do
items.Add ("one",1)
items.Add ("two",2)
items.Add ("three",3)
member this.TryGetValue (key,value) =
items.TrygetValue (key,value)
let c = MyClass ()
let d = Dictionary<string,int> ()
d.Add ("one",1)
d.Add ("two",2)
d.Add ("three",3)
And the following test code
let r1,v1 = d.TryGetValue "one"
let r2,v2 = c.TryGetValue "one"
The r1,v1 line works fine. The r2,v2 line bombs; complaining c.TryGetValue must be given a tuple. Interestingly, in each line the signature of TryGetValue is different. How can I get my custom implementation to exhibit the same behavior as the BCL version? Or, asked another way, since F# has (implicitly) the concept of tuple parameters, curried parameters, and BCL parameters, and I know how to distinguish between curried and tuple-style, how can I force the third style (a la BCL methods)?
Let me 开发者_Python百科know if this is unclear.
TryGetValue
has an out parameter, so you need to do the same in F# (via a byref
marked with OutAttribute
):
open System.Runtime.InteropServices
type MyDict<'K,'V when 'K : equality>() = // '
let d = new System.Collections.Generic.Dictionary<'K,'V>()
member this.TryGetValue(k : 'K, [<Out>] v: byref<'V>) =
let ok, r = d.TryGetValue(k)
if ok then
v <- r
ok
let d = new MyDict<string,int>()
let ok, i = d.TryGetValue("hi")
let mutable j = 0
let ok2 = d.TryGetValue("hi", &j)
F# automagically lets you turn suffix out parameters into return values, so you just need to author a method that ends in an out parameter.
Personally, I have never liked the bool TryXXX(stringToParseOrKeyToLookup, out parsedInputOrLookupValue_DefaultIfParseFailsOrLookupNotFound)
pattern used throughout the BCL. And while the F# trick of returning a tuple is nice, rarely if ever do I actually need the default value if a parse or lookup fails. Indeed, the Some
/None
pattern would be perfect (like Seq.tryFind
):
type MyClass () =
let items = System.Collections.Generic.Dictionary<string,int>()
do
items.Add ("one",1)
items.Add ("two",2)
items.Add ("three",3)
member this.TryGetValue (key) =
match items.TryGetValue(key) with
| (true, v) -> Some(v)
| _ -> None
let c = MyClass()
let printKeyValue key =
match c.TryGetValue(key) with
| Some(value) -> printfn "key=%s, value=%i" key value
| None -> printfn "key=%s, value=None" key
//> printKeyValue "three";;
//key=three, value=3
//val it : unit = ()
//> printKeyValue "four";;
//key=four, value=None
//val it : unit = ()
精彩评论