【问题标题】:philosophy behind http-simple setRequestBodyLBShttp-simple setRequestBodyLBS 背后的哲学
【发布时间】:2018-08-16 13:39:52
【问题描述】:

我正在尝试使用 http-simple 库开发一个 http 客户端。该库的某些实现让我感到困惑。

这个库大量使用了 Conduit;但是还有这个“setRequestBodyLBS”函数,有趣的是,这里缺少“setRequestBodyBS”函数。据记载,Conduit 和惰性 IO 不能很好地协同工作。所以我的问题是,为什么不反过来呢?即,实现功能的BS版本而不是LBS版本?这里做出的选择背后的想法是什么?

【问题讨论】:

  • Lazy IO 并不是获得惰性 ByteString 的唯一方法。

标签: haskell conduit lazy-io


【解决方案1】:

在内部,惰性字节串就像严格字节串的链表。移动from a strict bytestring to a lazy one 很便宜(您构建一个包含一个元素的链表),但进入reverse direction 成本更高(您需要为组合字节分配一块连续的内存,然后从列表中复制每个块)。

惰性 IO 使用惰性字节串,但它们在其他情况下也很有用,例如,当您有来自外部源的严格块并且您想要一种简单的方法来累积它们而不必预先分配大块内存或执行频繁的重新分配/复制。相反,您只需将稍后present 的块列表保留为惰性字节串。 (当列表连接开始变得昂贵或粒度太小时,您可以使用Builder 作为进一步优化。)

另一个常见的用例是一些复合数据结构的序列化(例如,aeson 的Value)。如果您要做的只是将生成的字节转储到文件或网络请求中,那么对每个子组件的序列化字节执行相对昂贵的合并是没有多大意义的。如果需要,您可以稍后随时使用toStrict 执行它。

【讨论】:

  • 例如,如果在一个 Conduit 中我收到一个严格的 ByteString 块,将其转换为惰性并调用 'setRequestBodyLBS' 将其发送出去,开销可以忽略不计,因为转换是 O(n);但这不利于异常处理吗?我已经看到它记录了当涉及惰性 IO 时,很难正确处理异常。
  • @user2812201 单独使用setRequestBodyLBS 不会执行惰性I/O,它是一个接受惰性字节串的完全正常的函数。同样,我怀疑您收到的 ByteString 来自惰性 I/O。事实上,像管道这样的流库的发明在很大程度上是为了避免惰性 I/O 的怪异和病态情况!不要使用来自System.IOhGetContentsgetContentsreadFile 等函数。但是使用通过其他方式获得的惰性字节串很好。
  • 非常感谢您的澄清!我收到的数据来自上游管道,实际上我收到了严格的 BS,必须转换为 LBS 才能由setRequestBodyLBS 发送出去。
猜你喜欢
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 2012-01-23
  • 1970-01-01
  • 2022-06-14
  • 1970-01-01
  • 1970-01-01
  • 2023-02-04
相关资源
最近更新 更多