Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does completing function do in Clojure?

I've came across completing function on clojuredocs but there is no doc at the moment.

Could you provide some examples?

like image 815
Ertuğrul Çetin Avatar asked Dec 13 '22 22:12

Ertuğrul Çetin


1 Answers

completing is used to augment a binary reducing function that may not have a unary overload with a unary "completion" arity.

The official transducers reference page hosted @ clojure.org explains the purpose of the nullary, unary and binary overloads of transducing functions and includes a good example of when the unary "completion" arity is useful in the section called "Creating Transducers" (the example used is partition-all which uses completion to produce the final block of output).

In short, the completion arity is used after all input is consumed and gives the transducing function the opportunity to perform any work to flush any buffers that the transducing process might maintain (as in the case of partition-all), apply any final transformations to the output (see below for an example of that) etc. Here by "transducing function" I mean the transducing function actually passed to transduce (or eduction or any similar function that sets up a transducing process) together with all the wrapping transducers.

For an interesting example of completing used with a non-trivial completion function, have a look at Christophe Grand's 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 Note, however, that clojure.core/str runs in linear time if used with apply – it uses a StringBuilder under the hood just like net.cgrand.xforms.rfs/str. It's still convenient from time to time to have a transduce-friendly version (for use with transducers, or in higher-order contexts, or possibly for performance reasons when dealing with a large collection that can be reduced be efficiently than via first/next looping that str uses).

like image 92
Michał Marczyk Avatar answered Jan 05 '23 00:01

Michał Marczyk