0
(defn multiply-xf
  []
  (fn [xf]
    (let [product (volatile! 1)]
      (fn
        ([] (xf))
        ([result]
         (xf result @product)
         (xf result))
        ([result input]
         (let [new-product (* input @product)]
           (vreset! product new-product)
           (if (zero? new-product)
             (do
               (println "reduced")
               (reduced ...)) <----- ???
             result)))))))  

这是一个简单的换能器,可以将数字倍增。我想知道reduced允许提前终止的价值是什么?

我已经尝试过(transient []),但这意味着换能器仅适用于矢量。

4

1 回答 1

1

我假设您希望此传感器生成一个正在运行的产品序列,并在产品达到零时提前终止。尽管在示例中,reduce 函数xf从未在 2-arity step函数中调用,并且在完成arity 中被调用了两次。

(defn multiply-xf
  []
  (fn [rf]
    (let [product (volatile! 1)]
      (fn
        ([] (rf))
        ([result] (rf result))
        ([result input]
         (let [new-product (vswap! product * input)]
           (if (zero? new-product)
             (reduced result)
             (rf result new-product))))))))

提前终止通知,我们不在乎是什么result。在您的示例中,这就是rf归约函数的职责。xf我还合并vreset!/@productvswap!.

(sequence (multiply-xf) [2 2 2 2 2])
=> (2 4 8 16 32)

如果正在运行的产品达到零,它将终止:

(sequence (multiply-xf) [2 2 0 2 2])
=> (2 4)

我们可以使用transduce对输出求和。这里的归约函数是+,但你的转换器不需要知道任何关于它的信息:

(transduce (multiply-xf) + [2 2 2 2])
=> 30

我已经尝试过(transient []),但这意味着换能器仅适用于矢量。

这个转换器也不需要关心它给出的序列/集合的类型。

(eduction (multiply-xf) (range 1 10))
=> (1 2 6 24 120 720 5040 40320 362880)
(sequence (multiply-xf) '(2.0 2.0 0.5 2 1/2 2 0.5))
=> (2.0 4.0 2.0 4.0 2.0 4.0 2.0)
(into #{} (multiply-xf) [2.0 2.0 0.5 2 1/2 2 0.5])
=> #{2.0 4.0}

这也可以在没有传感器的情况下完成:

(take-while (complement zero?) (reductions * [2 2 0 2 2]))
=> (2 4)
于 2018-01-06T14:32:14.407 回答