views:

204

answers:

1

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 know if this is unclear.

+6  A: 

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.

Brian
Thanks. I actually tried that, but didn't realize I needed the OutAttribute. I assumed the byref<'v> would be enough.
pblasucci
byref by itself is like 'ref' in C# (as opposed to C# 'out').
Brian
ah, yes: ref, out... just give me tuples any day!
pblasucci