在调用“完整”元数(即
[([result input] )
)之前,需要根据需要多次调用“步骤”元数(即([result] )
)来刷新其状态。
我的问题是这里如何处理提前终止(带
reduced
)。
关于https://clojure.org/reference/transducers#_early_termination 它说
在完成步骤中,具有缩减状态的转换器应该在调用嵌套转换器的完成函数之前刷新状态,除非它之前已经从嵌套步骤中看到一个缩减值,在这种情况下,挂起状态应该被丢弃。
但是“以前见过”是什么意思?
上述引述有三种可能的解释: 如果嵌套转换器的“步骤”参数返回了一个
reduced
值,那么“完成”步骤应该是
看
partition-by
的实现,似乎第一个选项适用:
([result]
(let [result (if (.isEmpty a)
result
(let [v (vec (.toArray a))]
;;clear first!
(.clear a)
(unreduced (rf result v))))]
(rf result)))
在将这个未减少的值传递给嵌套变换的“完整”元数之前,这也从使用剩余状态调用嵌套变换的“步骤”元数的结果中删除了“减少性”。
那么问题是,如果我有一个有状态的 reducer,它在其完成步骤中会多次调用其嵌套转换的“步骤”arity,如果它在其完成步骤中看到
reduced
值,它应该如何反应?
尝试结合上面的引用和代码,我认为它应该停止调用“步骤”参数并直接调用具有
unreduced
值的“完整”参数,如partition-by
。
但是,看看
cat
的代码:
(defn ^:private preserving-reduced
[rf]
#(let [ret (rf %1 %2)]
(if (reduced? ret)
(reduced ret)
ret)))
(defn cat
"A transducer which concatenates the contents of each input, which must be a
collection, into the reduction."
{:added "1.7"}
[rf]
(let [rrf (preserving-reduced rf)]
(fn
([] (rf))
([result] (rf result))
([result input]
(reduce rrf result input)))))
它将任何减少的结果包装在“步骤”数量中的另一个减少的“层”中。 (稍后被
reduce
删除?)
只是我在
partition-by
和cat
的实现中碰巧发现了两个特殊情况,还是关于在提前终止期间何时调用嵌套“step”函数以及“reducedness”如何调用有一些通用规则" 是否要传达(或不传达)?
据我了解,换能器应该只关心它自己的操作,而不关心它是如何使用或组成的,但这对提前终止有何影响?
此外,如果前者提前终止不影响后者,“步骤”和“完整”属性是否应被视为完全分开?