请分享您的看法,点击2024 Clojure调查问卷!

欢迎!有关更多信息,请参阅关于页面。

0
变换器
已关闭

当transducer与into一起使用时触发异常,但与sequence一起使用时不触发。

(sequence (halt-when #{4}) (range)) ;; => (0 1 2 3)
(into [] (halt-when #{4}) (range))
;; class java.lang.Long cannot be cast to class clojure.lang.ITransientCollection (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.ITransientCollection is in unnamed module of loader 'app')

我认为这是由于一个错误引起的,它返回的是输入而不是结果,我认为这个实现应该修复这个特定问题。

(defn halt-when1
  ([pred] (halt-when1 pred nil))
  ([pred retf]
   (fn [rf]
     (fn
       ([] (rf))
       ([result]
        (if (and (map? result) (contains? result ::halt))
          (::halt result)
          (rf result)))
       ([result input]
        (if (pred input)
          (reduced {::halt (if retf (retf (rf result) input) (rf result))})
          (rf result input)))))))

然而,我认为retf函数现在与变换上下文耦合。因此,如果您想将结果转换成,例如包含引发停止的输入,那么您需要知道在创建transducer时将会在特定上下文中使用,以及您需要调用conj、conj!或类似操作。因此,我认为这个函数的签名更有意义

(defn halt-when2
  ([pred] (halt-when2 pred nil))
  ([pred retf]
   (fn [rf]
     (fn
       ([] (rf))
       ([result]
        (if (and (map? result) (contains? result ::halt))
          (::halt result)
          (rf result)))
       ([result input]
        (if (pred input)
          (let [r (if retf
                    (retf rf result input)
                    result)]
            (reduced {::halt (rf r)}))
          (rf result input)))))))

这改变了retf函数的签名,以接受减少函数以及结果和输入,现在您可以决定做什么

(into [] (halt-when2 #{4} (fn [rf r i] (rf r i))) (range)) ;; => [0 1 2 3 4]

也许可以向halt-when添加一个第三个参数,一些选项映射,来告诉它我们传递了2个参数的retf还是3个参数的一个?这有意义吗?或者我可能是在要求一个新函数叫stop-at或者是其他什么?

--- 编辑 ---

刚刚发现这篇https://groups.google.com/g/clojure/c/6HvmJIUsXKk/m/gLqUsfcnAwAJ,我认为它更详细地解释了为什么返回输入的原因,但我仍然认为提供一种策略来转换结果,而无需知道实际的减少函数是什么,是有用的。

备注:已关闭,发布在1.11.0-alpha4

1 答案

0

关于此问题,我们已在 https://clojure.atlassian.net/browse/CLJ-2556 上创建了工单

...