How can I implement the same behavior as Dictionary.TryGetValue

So, given the 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" 

Line r1, v1 works fine. Linear bombs r2, v2; complaining that c.TryGetValue must have a tuple. Interestingly, on each line, the TryGetValue signature is different. How can I make my custom implementation exhibit the same behavior as the BCL version? Or, I asked for another way, since F # (implicitly) implies the concept of tuple parameters, parameters in curry and BCL parameters, and I know how to distinguish between curry and tuple style, how can I force the third style (a la BCL methods)?

Let me know if this is unclear.

+7
f # implementation
source share
2 answers

TryGetValue has an out parameter, so you need to do the same in F # (via 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 # automatically allows you to convert the suffix parameters to return values, so you just need to create a method that ends with the out parameter.

+8
source share

Personally, I never liked the bool TryXXX(stringToParseOrKeyToLookup, out parsedInputOrLookupValue_DefaultIfParseFailsOrLookupNotFound) used in BCL. And while the F # trick returning a tuple is good, rarely, if ever, do I really need a default value if parsing or searching does not work. Indeed, a Some / None pattern would be ideal (e.g. 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 = () 
+4
source share

All Articles