Clojure 我用什么来减少这个传感器? (defn乘xf [] (fn[xf] (让[产品(挥发性!1)] (fn ([](xf)) ([结果] (xf结果@产品) (xf结果) ([结果输入] (让[新产品(*输入@产品)] (vreset!产品新产品) (如果(零?新产品) (做 (println“减少”) (简化…)

Clojure 我用什么来减少这个传感器? (defn乘xf [] (fn[xf] (让[产品(挥发性!1)] (fn ([](xf)) ([结果] (xf结果@产品) (xf结果) ([结果输入] (让[新产品(*输入@产品)] (vreset!产品新产品) (如果(零?新产品) (做 (println“减少”) (简化…),clojure,transducer,Clojure,Transducer,我假设您希望此转换器生成一个运行的产品序列,并在产品为零时提前终止。尽管在本例中,简化函数xf从未在2-算术步长函数中调用,并且在完成算术中调用了两次 请注意,对于提前终止,我们不关心结果是什么。在您的示例中,这是减少函数rfa.k.axf的责任。我还将vreset!/

我假设您希望此转换器生成一个运行的产品序列,并在产品为零时提前终止。尽管在本例中,简化函数
xf
从未在2-算术步长函数中调用,并且在完成算术中调用了两次

请注意,对于提前终止,我们不关心
结果是什么。在您的示例中,这是减少函数
rf
a.k.a
xf
的责任。我还将
vreset!
/
vswap!
合并

(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))))))))
如果正在运行的产品达到零,它将终止:

(sequence (multiply-xf) [2 2 2 2 2])
=> (2 4 8 16 32)
我们可以使用
transduce
对输出进行求和。这里的归约函数是
+
,但您的传感器不需要知道任何有关这方面的信息:

(sequence (multiply-xf) [2 2 0 2 2])
=> (2 4)
我试过
(瞬态[])
,但这意味着传感器只能与矢量一起工作

该传感器本身也不需要考虑给定的序列/采集类型

(transduce (multiply-xf) + [2 2 2 2])
=> 30
这也可以在没有传感器的情况下完成:

(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}

谢谢,这确实解决了问题。但是,我尝试编写的传感器会产生一个输出。这样创建传感器是错误的吗?您可以使用传感器产生一个输出,就像上面的
transduce
示例中对乘积求和一样。“它们独立于其输入和输出源的上下文,仅根据单个元素指定转换的本质。”因此,在你的传感器内部建立一个单一值的意图似乎是不可取的。啊,是的,这就解释了。我对传感器如何工作的假设中有一个缺陷。:)
(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)