在 Clojure 中完成函数有什么作用?

What does completing function do in Clojure?

我在 clojuredocs 上遇到了 completing 函数,但目前没有文档。

你能提供一些例子吗?

completing 用于扩充二元缩减函数,该函数可能不具有一元 "completion" 元数的一元重载。

The official transducers reference page hosted @ clojure.org 解释了转换函数的 nullary、unary 和 binary 重载的目的,并在名为 "Creating Transducers" 的部分中提供了一个很好的示例,说明一元 "completion" 元数何时有用(使用的示例是 partition-all,它使用完成来生成最终的输出块)。

简而言之,在所有输入被消耗后使用完成元数,并使转换功能有机会执行任何工作以刷新转换过程可能维护的任何缓冲区(如 partition-all 的情况) ), 将任何最终转换应用于输出(参见下面的示例)等。这里 "transducing function" 我的意思是转换函数实际上传递给 transduce (或 eduction 或任何类似的设置换能过程的功能)以及所有包装换能器。

有关 completing 与非平凡完成函数一起使用的有趣示例,请查看 Christophe Grand 的 xforms: net.cgrand.xforms.rfs/str is a transduce-friendly version of clojure.core/str that will build up a string in linear time when used in a transduce call. (In contrast, clojure.core/str, if used in reduce/transduce, would create a new string at each step, and consequently run in O(n²) time.1) It uses completing to convert the StringBuilder that it uses under to hood to a string once it consumes all input. Here's a stable link to its definition as of the current tip of the master branch.


1 但是请注意,如果与 apply 一起使用,clojure.core/str 会以线性时间运行 - 它在引擎盖下使用 StringBuilder就像 net.cgrand.xforms.rfs/str。有时使用 transduce 友好版本仍然很方便(用于传感器,或在高阶上下文中,或者可能出于性能原因,在处理可以比通过有效减少的大型集合时first/next str 使用的循环。