【问题标题】:Why does filterv's predicate need to be free of side-effects?为什么 filterv 的谓词需要没有副作用?
【发布时间】:2019-01-28 05:57:28
【问题描述】:

终于在学习 Box2D(使用 cljbox2d port)。在我的“hello world 测试”中,我发现需要一个函数来检查框列表,销毁并从列表中删除超出范围的框。

我写的处理这个的基本函数是*:

(defn handle-out-of-bounds! [boxes]
  (filterv (fn [{:keys [body]}]
             (when-not (inbounds? (bc/position body))
               (bc/destroy! body)))
           boxes))

这里需要注意的是destroy!,顾名思义,会产生副作用。

我决定检查一下filterv 的来源,因为我实际上从未有过,并注意到文档字符串有警告:

。 . . pred 必须没有副作用。

为什么? filter 我可以看到。它是惰性的,因此除非您明确强制评估,否则您无法保证谓词实际上会在任何给定点运行。 filterv 是对列表的严格缩减;内部使用瞬态向量。唯一值得怀疑的是使用瞬变,但我看不出这会产生什么影响。

有没有实际上filterv的谓词中不执行副作用的有效理由,或者仅仅是一个概念上的理由?


* 写完才发现我的逻辑不对,这个函数实际上已经坏掉了,不过这不是重点。我也可以分别处理销毁和删除,但同样,这不是问题。

【问题讨论】:

    标签: clojure side-effects


    【解决方案1】:

    其他人之前对此感到困惑,例如在this mailing list post中看到相同的问题。

    那些发表评论的人似乎也同意所讨论的陈述没有动机。 filterv 是急切的,有副作用的 pred 没有问题。

    如果语句错误,可能的解释是文档字符串中的简单复制和粘贴错误。 mapvfilterv were introduced by Stuart Halloway,他们只是简单地复制了 mapfilter 的文档字符串,用“向量”替换了“惰性序列”。

    【讨论】:

    • 由于这是猜测,我会等着看是否还有其他消息,但如果你是对的,我不会感到惊讶。
    • 我已经打开了CLJ-2452 ...让我们看看情况如何。
    • 酷,谢谢。很高兴能澄清/解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多