@@ -129,13 +129,128 @@ module Dict =
129129 dct2.Add ( k, vy)
130130 dct1 :> IDictionary< 'Key, 'T1>, dct2 :> IDictionary< 'Key, 'T2>
131131
132+
133+ /// <summary>Creates a conceptually infinite dictionay containing the same value for all possible keys.</summary>
134+ /// <param name="source">The value for all possible keys.</param>
135+ let initInfinite < 'TKey , 'TValue > ( source : 'TValue ) : IDictionary < 'TKey , 'TValue > =
136+
137+ let icollection value =
138+ {
139+ new ICollection< 't> with
140+ member __.Contains ( item : 't ) = obj.ReferenceEquals ( item, value)
141+ member __.GetEnumerator () = ( Seq.initInfinite ( fun _ -> value)). GetEnumerator () :> System .Collections .IEnumerator
142+ member __.GetEnumerator () = ( Seq.initInfinite ( fun _ -> value)). GetEnumerator () : IEnumerator < 't >
143+ member __.IsReadOnly = true
144+
145+ member __.Add ( _item : 't ) : unit = raise ( System.NotImplementedException())
146+ member __.Clear () : unit = raise ( System.NotImplementedException())
147+ member __.CopyTo ( _array : 't [], _arrayIndex : int ) : unit = raise ( System.NotImplementedException())
148+ member __.Count : int = - 1
149+ member __.Remove ( _item : 't ): bool = raise ( System.NotImplementedException())
150+ }
151+
152+ {
153+ new IDictionary< 'TKey, 'TValue> with
154+ member __.TryGetValue ( _key : 'TKey , value : byref < 'TValue >) = value <- source; true
155+ member __.Count = - 1
156+ member __.ContainsKey ( _key : 'TKey ) = true
157+ member __.Contains ( item : KeyValuePair < 'TKey , 'TValue >) = obj.ReferenceEquals ( item.Value, source)
158+ member __.GetEnumerator () = invalidOp " Key set is potentially infinite." : System .Collections .IEnumerator
159+ member __.GetEnumerator () = invalidOp " Key set is potentially infinite." : IEnumerator < KeyValuePair < 'TKey , 'TValue >>
160+ member __.IsReadOnly = true
161+ member __.Values = icollection source
162+ member __.Item
163+ with get ( _key : 'TKey ) : 'TValue = source
164+ and set ( _key : 'TKey ) ( _ : 'TValue ) : unit = raise ( System.NotImplementedException())
165+
166+ member __.Add ( _key : 'TKey , _value : 'TValue ) : unit = raise ( System.NotImplementedException())
167+ member __.Add ( _item : KeyValuePair < 'TKey , 'TValue >) : unit = raise ( System.NotImplementedException())
168+ member __.Clear () : unit = raise ( System.NotImplementedException())
169+ member __.CopyTo ( _arr : KeyValuePair < 'TKey , 'TValue > [], _arrayIndex : int ) : unit = raise ( System.NotImplementedException())
170+ member __.Keys : ICollection < 'TKey > = raise ( System.NotImplementedException())
171+ member __.Remove ( _key : 'TKey ) : bool = raise ( System.NotImplementedException())
172+ member __.Remove ( _item : KeyValuePair < 'TKey , 'TValue >) : bool = raise ( System.NotImplementedException())
173+ }
174+
175+ let initHybrid < 'TKey , 'TValue > ( konst : 'TValue ) ( source : IDictionary < 'TKey , 'TValue >) : IDictionary < 'TKey , 'TValue > =
176+
177+ let icollection ( konst : 'TValue ) ( source : IDictionary < 'TKey , 'TValue >) =
178+ {
179+ new ICollection< 't> with
180+ member __.Contains ( item : 't ) = source.Values.Contains item || obj.ReferenceEquals ( item, konst)
181+ member __.GetEnumerator () = ( seq { yield ! source.Values; yield ! ( Seq.initInfinite ( fun _ -> konst))}). GetEnumerator () :> System.Collections.IEnumerator
182+ member __.GetEnumerator () = ( seq { yield ! source.Values; yield ! ( Seq.initInfinite ( fun _ -> konst))}) .GetEnumerator () : IEnumerator< 't>
183+ member __.IsReadOnly = true
184+
185+ member __.Add ( _item : 't ) : unit = raise ( System.NotImplementedException())
186+ member __.Clear () : unit = raise ( System.NotImplementedException())
187+ member __.CopyTo ( _array : 't [], _arrayIndex : int ) : unit = raise ( System.NotImplementedException())
188+ member __.Count : int = - source.Count-1
189+ member __.Remove ( _item : 't ): bool = raise ( System.NotImplementedException())
190+ }
191+ {
192+ new IDictionary< 'TKey, 'TValue> with
193+ member __.TryGetValue ( key : 'TKey , value : byref < 'TValue >) =
194+ match source.TryGetValue key with
195+ | true , v -> value <- v
196+ | _ -> value <- konst
197+ true
198+ member __.Count = - source.Count-1
199+ member __.ContainsKey ( _key : 'TKey ) = true
200+ member __.Contains ( item : KeyValuePair < 'TKey , 'TValue >) =
201+ match source.TryGetValue item.Key with
202+ | true , v -> obj.ReferenceEquals ( item.Value, v)
203+ | _ -> obj.ReferenceEquals ( item.Value, konst)
204+ member __.GetEnumerator () = source.GetEnumerator () : System .Collections .IEnumerator
205+ member __.GetEnumerator () = source.GetEnumerator () : IEnumerator < KeyValuePair < 'TKey , 'TValue >>
206+ member __.IsReadOnly = true
207+ member __.Values = icollection konst source
208+ member __.Item
209+ with get ( key : 'TKey ) : 'TValue = match source.TryGetValue key with ( true , v) -> v | _ -> konst
210+ and set ( _key : 'TKey ) ( _ : 'TValue ) : unit = raise ( System.NotImplementedException())
211+
212+ member __.Add ( _key : 'TKey , _value : 'TValue ) : unit = raise ( System.NotImplementedException())
213+ member __.Add ( _item : KeyValuePair < 'TKey , 'TValue >) : unit = raise ( System.NotImplementedException())
214+ member __.Clear () : unit = raise ( System.NotImplementedException())
215+ member __.CopyTo ( _arr : KeyValuePair < 'TKey , 'TValue > [], _arrayIndex : int ) : unit = raise ( System.NotImplementedException())
216+ member __.Keys : ICollection < 'TKey > = raise ( System.NotImplementedException())
217+ member __.Remove ( _key : 'TKey ) : bool = raise ( System.NotImplementedException())
218+ member __.Remove ( _item : KeyValuePair < 'TKey , 'TValue >) : bool = raise ( System.NotImplementedException())
219+ }
220+
132221 /// Returns the union of two dictionaries, using the combiner function for duplicate keys.
133222 let unionWith combiner ( source1 : IDictionary < 'Key , 'Value >) ( source2 : IDictionary < 'Key , 'Value >) =
134- let d = Dictionary< 'Key, 'Value> ()
135- let f = OptimizedClosures.FSharpFunc<_,_,_>. Adapt combiner
136- for KeyValue( k, v ) in source1 do d.[ k] <- v
137- for KeyValue( k, v') in source2 do d.[ k] <- match d.TryGetValue k with true , v -> f.Invoke ( v, v') | _ -> v'
138- d :> IDictionary< 'Key, 'Value>
223+ let combine () =
224+ let d = Dictionary< 'Key, 'Value> ()
225+ let f = OptimizedClosures.FSharpFunc<_,_,_>. Adapt combiner
226+ for KeyValue( k, v ) in source1 do d.[ k] <- v
227+ for KeyValue( k, v') in source2 do d.[ k] <- match d.TryGetValue k with true , v -> f.Invoke ( v, v') | _ -> v'
228+ d :> IDictionary< 'Key, 'Value>
229+ let combineWithKonst source konst =
230+ let d = Dictionary< 'Key, 'Value> ()
231+ for KeyValue( k, v) in source do d.[ k] <- combiner v konst
232+ d :> IDictionary< 'Key, 'Value>
233+ let combineKonstWith konst source =
234+ let d = Dictionary< 'Key, 'Value> ()
235+ for KeyValue( k, v) in source do d.[ k] <- combiner konst v
236+ d :> IDictionary< 'Key, 'Value>
237+ match source1.Count, source2.Count with
238+ | - 1 , - 1 ->
239+ initInfinite (
240+ combiner
241+ ( source1[ Unchecked.defaultof< 'Key>])
242+ ( source2[ Unchecked.defaultof< 'Key>]))
243+ | - 1 , 0 -> source1
244+ | 0 , - 1 -> source2
245+ | - 1 , x when x < - 1 -> initHybrid ( combiner ( source1[ Unchecked.defaultof< 'Key>]) ( source2[ Unchecked.defaultof< 'Key>])) ( combineKonstWith ( source1[ Unchecked.defaultof< 'Key>]) source2)
246+ | x, - 1 when x < - 1 -> initHybrid ( combiner ( source1[ Unchecked.defaultof< 'Key>]) ( source2[ Unchecked.defaultof< 'Key>])) ( combineWithKonst source1 ( source2[ Unchecked.defaultof< 'Key>]))
247+ // Note: this is horrible and Unchecked.defaultof<'Key> is 0 for int keys, so it might not return the default value.
248+ // All this hints that a specific (named) class is needed, something like DictWithDefaultValue<'Key, 'Value> then type tests can be added before reading the defaultValue property.
249+ | x, y when x < - 1 && y < - 1 -> initHybrid ( combiner ( source1[ Unchecked.defaultof< 'Key>]) ( source2[ Unchecked.defaultof< 'Key>])) ( combine())
250+ | - 1 , _ -> combineKonstWith ( source1[ Unchecked.defaultof< 'Key>]) source2 |> initHybrid ( source1[ Unchecked.defaultof< 'Key>])
251+ | _, - 1 -> combineWithKonst source1 ( source2[ Unchecked.defaultof< 'Key>]) |> initHybrid ( source2[ Unchecked.defaultof< 'Key>])
252+ | _, _ -> combine()
253+
139254
140255 #if ! FABLE_ COMPILER
141256 ///Returns the union of two maps, preferring values from the first in case of duplicate keys.
@@ -179,44 +294,4 @@ module Dict =
179294 | None -> ()
180295 dct :> IDictionary< 'Key, 'U>
181296
182- /// <summary>Creates a conceptually infinite dictionay containing the same value for all possible keys.</summary>
183- /// <param name="source">The value for all possible keys.</param>
184- let initInfinite < 'TKey , 'TValue > ( source : 'TValue ) : IDictionary < 'TKey , 'TValue > =
185-
186- let icollection value =
187- {
188- new ICollection< 't> with
189- member __.Contains ( item : 't ) = obj.ReferenceEquals ( item, value)
190- member __.GetEnumerator () = ( Seq.initInfinite ( fun _ -> value)). GetEnumerator () :> System .Collections .IEnumerator
191- member __.GetEnumerator () = ( Seq.initInfinite ( fun _ -> value)). GetEnumerator () : IEnumerator < 't >
192- member __.IsReadOnly = true
193-
194- member __.Add ( _item : 't ) : unit = raise ( System.NotImplementedException())
195- member __.Clear () : unit = raise ( System.NotImplementedException())
196- member __.CopyTo ( _array : 't [], _arrayIndex : int ) : unit = raise ( System.NotImplementedException())
197- member __.Count : int = raise ( System.NotImplementedException())
198- member __.Remove ( _item : 't ): bool = raise ( System.NotImplementedException())
199- }
200-
201- {
202- new IDictionary< 'TKey, 'TValue> with
203- member __.TryGetValue ( _key : 'TKey , value : byref < 'TValue >) = value <- source; true
204- member __.Count = System.Int32.MaxValue
205- member __.ContainsKey ( _key : 'TKey ) = true
206- member __.Contains ( item : KeyValuePair < 'TKey , 'TValue >) = obj.ReferenceEquals ( item.Value, source)
207- member __.GetEnumerator () = invalidOp " Key set is potentially infinite." : System .Collections .IEnumerator
208- member __.GetEnumerator () = invalidOp " Key set is potentially infinite." : IEnumerator < KeyValuePair < 'TKey , 'TValue >>
209- member __.IsReadOnly = true
210- member __.Values = icollection source
211- member __.Item
212- with get ( _key : 'TKey ) : 'TValue = source
213- and set ( _key : 'TKey ) ( _ : 'TValue ) : unit = raise ( System.NotImplementedException())
214297
215- member __.Add ( _key : 'TKey , _value : 'TValue ) : unit = raise ( System.NotImplementedException())
216- member __.Add ( _item : KeyValuePair < 'TKey , 'TValue >) : unit = raise ( System.NotImplementedException())
217- member __.Clear () : unit = raise ( System.NotImplementedException())
218- member __.CopyTo ( _arr : KeyValuePair < 'TKey , 'TValue > [], _arrayIndex : int ) : unit = raise ( System.NotImplementedException())
219- member __.Keys : ICollection < 'TKey > = raise ( System.NotImplementedException())
220- member __.Remove ( _key : 'TKey ) : bool = raise ( System.NotImplementedException())
221- member __.Remove ( _item : KeyValuePair < 'TKey , 'TValue >) : bool = raise ( System.NotImplementedException())
222- }
0 commit comments