I was somewhat surprised when I realised that F#'s map
implements both IDictionary<'Key, 'Value> and ICollection<KeyValuePair<'a, 'b>>
considering that both supports mutation (add and remove) as part of the contract.
Looking at the implementation of map
it simply excepts when you try to cause mutation!
let map = [| (1, "one"); (2, "two") |] |> Map.ofArray
let dict = map :> IDictionary<int, string>
dict.Add(3, "three");;
the above code throws the exception:
System.NotSupportedException: Map values cannot be mutated. at Microsoft.FSharp.Collections.FSharpMap
2.System-Collections-Generic-IDictionary
2-Add(TKey k, TValue v) at .$FSI_0007.main@() Stopped due to error
which is as expected.
For an immutable collection to be able to expose itself as a mutable one only for it to throw exception when the consumer of that collection tries to cause mutation seems such a dangerous decision.
Am I missing something here?
more ... A special relationship where each input has a single output. It is often written as "f(x)" where x is the input value. Example: f(x) = x/2 ("f of x equals x divided by 2")
This formula, or new function, is called the derivative of the original function. When we find it we say that we are differentiating the function. The derivative of f(x) is written using an apostrophe after the f. The notation is f´(x) or y´ The notation dy/dx is also commonly used.
The slope of a linear function is calculated by rearranging the equation to its general form, f(x) = mx + c; where m is the slope. The vertex of a quadratic function is calculated by rearranging the equation to its general form, f(x) = a(x – h)2 + k; where (h, k) is the vertex.
I think the main reason is that .NET does not have any interface that represents immutable (part of an interface of a) dictionary. This means that all .NET APIs have to take IDictionary<K, V>
as parameter, even if they only intend to read from the dictionary. So:
Implementing IDictionary<'K, 'V>
is pretty much the only way to make the F# immutable map usable as a parameter to any .NET libraries that need an object that supports lookup. Sadly, there is no read-only alternative in .NET.
Implementing ICollection<KeyValuePair<'K, 'V>>
does not make too much sense to me, because there is a read-only alternative IEnumerable<KeyValuePair<'K, 'V>>
and immutable map implements this interface too.
But perhaps there are some .NET libraries that take ICollection<'T>
(for efficientcy - i.e. to get Count
without enumerating all elements) and use it in a read-only way.
EDIT: As noted by Daniel in the comment, implementing ICollection
is required, because the IDictionary
interface inherits from it.
I think the lack of read-only interface is quite unfortunate, but there is probably no way this could be fixed, because it would mean changing the existing .NET collection libraries.
IsReadOnly
allows for the interface to be read-only even though it provides writable methods.
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