我正在寻找一种方法来记忆OCaml函数f
的结果,该函数采用两个参数(通常更多)。另外(这是困难的部分),如果两个参数的任何一个值都被垃圾收集,我希望这个过程的底图完全忘记一个结果。
对于只接受一个参数的函数,可以使用Weak
模块及其Make
仿函数以简单的方式完成此操作。为了将这一点概括为可以记忆更高级别的函数的东西,一个天真的解决方案是创建一个从值元组到结果值的弱映射。但是这在垃圾收集方面无法正常工作,因为值的元组仅存在于memoization函数的范围内,而不是调用f
的客户端代码。实际上,弱引用将是元组,它将在备忘录后立即进行垃圾收集(在最坏的情况下)。
有没有办法在不重新实施Weak.Make
的情况下执行此操作?
Hash-consing与我的要求是正交的,事实上,我的价值观并不合适。
谢谢!
答案 0 :(得分:3)
一个想法是执行自己的垃圾收集。
为简单起见,我们假设所有参数都具有相同的类型k
。
除了包含k * k
键控的memoized结果的主弱表外,还要创建一个包含k
类型单个参数的辅助弱表。我的想法是偶尔扫描主表并删除不再需要的绑定。这是通过查找辅助表中的参数来完成的;然后,如果它们中的任何一个消失,你将从主表中删除绑定。
(免责声明:我没有对此进行测试;它可能无效或可能有更好的解决方案)
答案 1 :(得分:3)
不是通过元组索引,而是可以使用树结构。你有一个弱表由第一个函数参数索引,其参数是次要弱表。辅助表将由第二个函数参数索引,并包含已记忆的结果。一旦函数参数被GCed,该结构将忘记memoized函数结果。但是,只要第一个函数参数处于活动状态,就会保留辅助表本身。根据功能结果的大小和不同的第一个参数的分布,这可能是一个合理的权衡。
我也没有测试过这个。它似乎也相当明显。
答案 2 :(得分:1)
我知道这是一个老问题,但我的同事最近开发了一个名为Adapton的增量计算库,可以处理这个功能。您可以找到代码here。您可能希望使用LazySABidi仿函数(其他仿函数用于基准测试)。您可以在Applications文件夹中查看有关如何使用库的示例。如果您还有其他问题,请与我们联系。