【问题标题】:Lazy vs Strict implementations of data structures数据结构的惰性与严格实现
【发布时间】:2013-04-30 09:32:13
【问题描述】:

有一个具有惰性和严格实现的数据结构列表:

  • Data.Map.LazyData.Map.Strict
  • Data.IntMap.LazyData.IntMap.Strict
  • Data.HashMap.LazyData.HashMap.Strict
  • Data.ByteString.LazyData.ByteString.Strict
  • Data.Text.LazyData.Text

这些实现的优势和劣势是什么?在选择特定实现时要遵循哪些规则?

【问题讨论】:

  • 我对你没有任何严格的(呵呵)规则,但我倾向于选择懒惰,除非我有充分的理由不这样做。惰性结构表现得更自然,更适合语言的其余部分。

标签: haskell containers


【解决方案1】:
  • Data.XYMap.LazyData.XYMap.Strict

对于{"", "Int", "Hash"} 中的XY*.Strict 变体强制将映射到的值评估为 WHNF,然后再将它们放入映射中。

这样做的最大优势是更可预测的空间和时间行为,因为构建巨大的 thunk 要困难得多,尤其是对于表单类型 (ConstructorN UnboxedValueTypeN),这是不可能的。

缺点 - 我记得在讨论严格或惰性变体是否应该成为默认变体时提出了一些例子,但我不记得有什么特别的。

啊,刚刚想起一个用例:Lazy 变体可以打结,Strict 版本当然不可能!所以如果你这样做:Lazy.

我默认使用Strict 版本。直到我需要打结或遇到另一个我认为Lazy 变体优越的用例之前,我不知道什么时候会使用它们。

  • Data.(ByteString/Text).LazyData.(ByteString/Text).Strict

严格版本使用一个单一的存储块来存储有效负载,这意味着您可以快速随机访问,不仅可以顺序访问,还可以从末尾向后或来回跳转。

惰性版本基本上是严格块的头严格列表,它们的优势在于它们的顺序消耗通常可以在恒定的小内存中完成,如果您需要顺序处理大文件,那就太好了。

对于小(ish)数据,绝对使用Strict 变体,对于大数据,如果数据是按顺序(或多或少)处理的,则使用Lazy 变体。

【讨论】:

  • 请注意,Strict 变体在函数参数方面甚至非常严格,例如传递给 findWithDefault 的默认值,这通常不是您所期望的,即使是故意使用一张严格的地图。
【解决方案2】:

这些实现的优势和劣势是什么?在选择特定实现时要遵循哪些规则?

类型的严格或懒惰导致特定操作或使用模式的复杂性不同。

没有硬性或快速的规则 - 相反,您可能希望将它们视为完全不同的数据类型。

如果你坚持一些准则:

  • 大于内存的数据的惰性结构
  • 惰性结构用于不经常使用的数据或当您使用大型结构的一小部分时

然后:

  • 如果您进行大量更新,则需要严格的结构
  • 小型原子数据的严格结构

【讨论】:

    猜你喜欢
    • 2012-11-14
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-16
    • 1970-01-01
    相关资源
    最近更新 更多