When I try to extend IDictionary with the following code
type Generic.IDictionary<'TKey, 'TValue> with
member this.GetOrAdd (key:'TKey, fun':'TKey -> 'TValue) =
match this.ContainsKey(key) with
| true -> this.Item(key)
| false ->
let val_ = fun' key
this.Add(key, val_)
val_
let dd = dict[(1,2); (3,4)]
let f = fun x -> 2*x
let d5 = dd.GetOrAdd(5, f)
I got the following error in runtime.
System.NotSupportedException: Exception of type >'System.NotSupportedException' was thrown. at Microsoft.FSharp.Core.ExtraTopLevelOperators.dictValueType@98.System->Collections-Generic-IDictionary
2-Add(TKey key, T value) at FSI_0011.IDictionary
2.GetOrAdd[TKey,TValue](IDictionary2 this, >TKey key, FSharpFunc
2 fun') in >D:\BaiduYunDownload\DroiEtl\Droi.MyToPG\Util.Sync.fs:line 259 at .$FSI_0018.main@() in >D:\BaiduYunDownload\DroiEtl\Droi.MyToPG\Util.Sync.fs:line 264 Stopped due to error
But the compiler doesn't complain when building... Please help me...
dict
is documented to return a read-only IDictionary<_,_>
– you then call .Add
on it, and the backing class rightly throws an exception.
Create a real Dictionary
instance instead and you'll see it works as expected:
open System.Collections.Generic
type IDictionary<'TKey, 'TValue> with
member this.GetOrAdd (key:'TKey, fun':'TKey -> 'TValue) =
match this.ContainsKey key with
| true -> this.Item key
| false -> let val' = fun' key
this.Add (key, val')
val'
let dd =
let d = Dictionary()
d.Add (1, 2)
d.Add (3, 4)
d
printfn "%A" dd
dd.GetOrAdd (5, (fun x -> 2 * x)) |> printfn "%A :: %d" dd
dd.GetOrAdd (5, (fun x -> 9 * x)) |> printfn "%A :: %d" dd
Output:
seq [[1, 2]; [3, 4]]
seq [[1, 2]; [3, 4]; [5, 10]] :: 10
seq [[1, 2]; [3, 4]; [5, 10]] :: 10
Online Demo
Implementation-wise, @JoelMueller's suggestion is an obvious improvement:
type IDictionary<'TKey, 'TValue> with
member this.GetOrAdd (key:'TKey, fun':'TKey -> 'TValue) =
match this.TryGetValue key with
| true, val' -> val'
| false, _ -> let val' = fun' key
this.Add (key, val')
val'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With