Как я могу реализовать то же поведение, что и Dictionary.TryGetValue - PullRequest
7 голосов
/ 28 апреля 2010

Итак, учитывая затем следующий код

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)

И следующий код теста

let r1,v1 = d.TryGetValue "one"
let r2,v2 = c.TryGetValue "one"

Линия r1, v1 работает нормально. Линейные бомбы r2, v2; Жалоба c.TryGetValue должна иметь кортеж. Интересно, что в каждой строке подпись TryGetValue отличается. Как я могу заставить мою собственную реализацию показывать то же самое поведение как версия BCL? Или, если спросить по-другому, так как F # имеет (неявно) концепцию параметров кортежа, параметров карри и параметров BCL, и я знаю, как различать карри и стиль кортежа, как я могу форсировать третий стиль (как методы BCL )?

Дайте мне знать, если это неясно.

Ответы [ 2 ]

8 голосов
/ 28 апреля 2010

TryGetValue имеет выходной параметр, поэтому вам нужно сделать то же самое в F # (через byref, отмеченное 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 # позволяет автоматически преобразовывать суффиксные параметры в возвращаемые значения, поэтому вам просто нужно создать метод, заканчивающийся выходным параметром.

4 голосов
/ 06 декабря 2010

Лично мне никогда не нравился шаблон bool TryXXX(stringToParseOrKeyToLookup, out parsedInputOrLookupValue_DefaultIfParseFailsOrLookupNotFound), используемый в BCL. И хотя прием F # с возвратом кортежа - это хорошо, редко, если вообще когда-либо мне действительно нужно значение по умолчанию, если синтаксический анализ или поиск не удается. Действительно, шаблон Some / None был бы идеальным (как 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 = ()
...