dictionary - F# 中不可变的可变字典

标签 dictionary f#

我有声明可变字典的代码,但是当我尝试更改元素时会出错。
编码:

   let layers =
        seq {
            if recipes.ContainsKey(PositionSide.Short) then yield! buildLayerSide recipes.[PositionSide.Short]
            if recipes.ContainsKey(PositionSide.Long)  then yield! buildLayerSide recipes.[PositionSide.Long]
        }
        |> Seq.map (fun l -> l.Id, l)
        |> dict
这将创建一个 IDictionary .我知道对象本身是不可变的,但字典的内容应该是可变的。
当我通过显式初始化字典来更改代码时,它变得可变:
   let layers =
        let a =
            seq {
                if recipes.ContainsKey(PositionSide.Short) then yield! buildLayerSide recipes.[PositionSide.Short]
                if recipes.ContainsKey(PositionSide.Long)  then yield! buildLayerSide recipes.[PositionSide.Long]
            }
            |> Seq.map (fun l -> l.Id, l)
            |> dict
    let x = Dictionary<string, Layer>()
    a
    |> Seq.iter (fun kvp -> x.[kvp.Key] <- kvp.Value)

    x
这是为什么?

最佳答案

IDictionary是一个接口(interface),而不是一个类。这个接口(interface)可能有多种不同的实现。你甚至可以自己做一个。Dictionary确实是这些实现之一。它支持界面的全部功能。
但这不是 dict 的实现。函数返回。让我们试试这个:

> let d = dict [(1,2)]
> d.GetType().FullName
"Microsoft.FSharp.Core.ExtraTopLevelOperators+DictImpl`3[...
结果是 dict 的实现函数返回是Microsoft.FSharp.Core.ExtraTopLevelOperators.DictImpl - 一个名为 DictImpl 的类在 F# 标准库的内部深处定义。
碰巧该接口(interface)上的某些方法会抛出 NotSupportedException :
> d.Add(4,5)
System.NotSupportedException: This value cannot be mutated
这是设计使然。它是故意这样做的,以支持“默认情况下的不变性”。
如果你真的想要一个可变版本,你可以使用 Dictionary 之一来创建一个副本。的构造函数:
> let m = Dictionary(d)
> m.Add(4,5)  // Works now
Map 之间的区别和 Dictionary是实现,这意味着内存和运行时特性。Dictionary是一个哈希表。它提供恒定时间的插入和检索,但要为此付出代价,它依赖于其 key 的一致散列,并且它的更新是破坏性的,这也带来了线程不安全。Map被实现为一棵树。它提供对数插入和检索,但作为返回具有 persistent data structure 的好处.此外,它要求 key 具有可比性。试试这个:
> type Foo() = class end
> let m = Map [(Foo(), "bar")]
error FS0001: The type 'Foo' does not support the 'comparison' constraint
比较键对于构建树至关重要。

关于dictionary - F# 中不可变的可变字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65059094/

相关文章:

python - 如何将给定的 Excel 文件转换为 Python 中的字典?

java - 如何将 HashMap 值传递给列表

.net - F# 静态成员约束结合 IDisposable

unit-testing - 将可区分的联合传递给 InlineData 属性

f# 允许 cors web api

f# - FSharp--过滤掉无的最短方法?

python - 如何使此排序不区分大小写?

python - 如何在Python中将字典转换为数据框

string - 将一百万个字符串映射到 C++11 中的整数

data-structures - 实现不可变的、可增长的向量