像Java's weak hash map这样的弱哈希表使用弱引用来跟踪垃圾收集器的无法访问密钥的集合,并从集合中删除与该密钥的绑定。弱哈希表通常用于实现从图中的一个顶点或边到另一个的间接,因为它们允许垃圾收集器收集图中不可到达的部分。
这个数据结构是否有纯功能等价物?如果没有,怎么可能创建一个?
这似乎是一个有趣的挑战。内部实现不能是纯粹的,因为它必须收集(即变异)数据结构以删除无法访问的部分,但我相信它可以为用户提供纯粹的接口,用户永远不会观察到杂质,因为它们只会影响数据的某些部分根据定义,用户可以不再到达的结构。
答案 0 :(得分:2)
这是一个有趣的概念。 “纯功能”设置中的一个主要复杂因素是对象身份通常不会在“纯粹功能”的意义上被观察到。 I.E.,如果我复制一个对象或创建一个新的相同的对象,在Java中,预计该克隆不是原始的。但是在功能设置中,预计新版本在语义上与旧版本相同,即使垃圾收集器会以不同方式对待它。
因此,如果我们允许对象标识成为语义的一部分,那么它将是合理的,否则可能不是。在后一种情况下,即使可以找到一个黑客(我想到了一个,如下所述),你很可能会让语言实现与你争分夺秒,因为它会做各种事情来利用这个事实该对象标识不应该是可观察的。
突然出现在我脑海中的一个'黑客'将是使用构造值的唯一值作为键,因此大多数情况下值相等将与引用相等重合。例如,我有一个我在Haskell中亲自使用的库,其界面中包含以下内容:
data Uniq s
getUniq :: IO (Uniq RealWorld)
instance Eq (Uniq s)
instance Ord (Uniq s)
你所描述的哈希映射可能大部分都是以这些为关键,但即使在这里我也能想到它可能会破坏的方式:假设用户将密钥存储在某些数据结构的严格字段中,使用编译器启用“unbox-strict-fields”优化。如果'Uniq'只是机器整数的新类型包装器,那么GC可能不再指向任何对象并说“那是关键”;因此,当用户去解压缩他的密钥以使用它时,地图可能已经忘记了它。 (编辑:这个特定的例子显然可以解决;使Uniq的实现不能像那样拆箱;关键是它很棘手,因为编译器试图在很多方面帮助我们可能没有期望)
TL; DR:我不会说它无法完成,但我怀疑在许多情况下,“优化”会破坏或被弱哈希映射实现破坏,除非给出一流的对象标识可观察的状态。
答案 1 :(得分:0)
纯功能数据结构不能从用户角度改变。所以,如果我从哈希映射中获取密钥,等待,然后再次获得相同的密钥,我必须得到相同的值。我可以握住钥匙,所以它们不会消失。
唯一可行的方法是,如果API为我提供下一代,并且在释放对过去版本容器的所有引用之前不会收集值。预计数据结构的用户会定期要求新一代发布弱持有的值。
编辑(基于评论):我理解你想要的行为,但你不能通过发布对象的地图传递这个测试:
FunctionalWeakHashMap map = new FunctionalWeakHashMap();
{ // make scope to make o have no references
Object o = new SomeObject();
map["key"] = o;
} // at this point I lose all references to o, and the reference is weak
// wait as much time as you think it takes for that weak reference to collect,
// force it, etc
Assert.isNotNull(map["key"]); // this must be true or map is not persistent
我建议这个测试可以通过
FunctionalWeakHashMap map = new FunctionalWeakHashMap();
{ // make scope to make o have no references
Object o = new SomeObject();
map["key"] = o;
} // at this point I lose all references to o, and the reference is weak in the map
// wait as much time as you think it takes for that weak reference to collect,
// force it, etc
map = map.nextGen();
Assert.isNull(map["key"]);