<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://vincent.404.taipei/feed.xml" rel="self" type="application/atom+xml" /><link href="https://vincent.404.taipei/" rel="alternate" type="text/html" /><updated>2022-06-06T09:58:00+00:00</updated><id>https://vincent.404.taipei/feed.xml</id><title type="html">Vincent Cantin’s blog</title><subtitle>On programming with Clojure.</subtitle><author><name>Vincent Cantin</name></author><entry><title type="html">Building trees with and without zippers</title><link href="https://vincent.404.taipei/clojure/building-trees-with-and-without-zippers/" rel="alternate" type="text/html" title="Building trees with and without zippers" /><published>2019-04-07T00:00:00+00:00</published><updated>2019-04-07T00:00:00+00:00</updated><id>https://vincent.404.taipei/clojure/building-trees-with-and-without-zippers</id><content type="html" xml:base="https://vincent.404.taipei/clojure/building-trees-with-and-without-zippers/">&lt;p&gt;In his &lt;a href=&quot;https://lambdaisland.com/blog/2018-11-26-art-tree-shaping-clojure-zip&quot;&gt;blog post and video&lt;/a&gt;
from november 2018, Arne Brasseur explains the idea behind the functional zippers
in the &lt;code&gt;clojure.zip&lt;/code&gt; namespace.
He describes how to use them to navigate existing tree-shaped data structures
and how to modify them.&lt;/p&gt;

&lt;p&gt;There is something that he did not mention explicitly, it is that they are &lt;strong&gt;an excellent choice&lt;/strong&gt; when you don’t
have a tree but need to build one.&lt;/p&gt;

&lt;h1 id=&quot;from-sequence-to-tree&quot;&gt;From sequence to tree&lt;/h1&gt;

&lt;p&gt;As an example, suppose that you have the following sequence of data:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-clojure&quot;&gt;(def elements [{:type :todo-list
                :name &quot;Things I should do today&quot;}
               {:type :text
                :value &quot;Buy some bread&quot;}
               {:type :url-list
                :title &quot;Read blogs&quot;}
               {:type :url
                :value &quot;https://vincent.404.taipei&quot;}
               {:type :url
                :value &quot;https://lambdaisland.com/blog&quot;}
               {:type :text
                :value &quot;Look for some interesting Clojure blogs.&quot;}
               {:type :url-list-end}
               {:type :foo
                :value :bar}
               {:type :todo-list-end}
               {:type :life
                :description &quot;Take the time to relax&quot;}])
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, suppose that what you really want is a tree structure like that one:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-clojure&quot;&gt;[{:type :todo-list
  :name &quot;Things I should do today&quot;
  :children [{:type :text
              :value &quot;Buy some bread&quot;}
             {:type :url-list
              :title &quot;Read blogs&quot;
              :children [{:type :url
                          :value &quot;https://vincent.404.taipei&quot;}
                         {:type :url
                          :value &quot;https://lambdaisland.com/blog&quot;}
                         {:type :comment
                          :value &quot;Look for some interesting Clojure blogs.&quot;}]}
             {:type :foo
              :value :bar}]}
 {:type :life
  :description &quot;Take the time to relax&quot;}]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In order to do the transformation, you would intuitively need to:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;find the beginning and the end of each block in the sequence,&lt;/li&gt;
  &lt;li&gt;build a tree node for each block,&lt;/li&gt;
  &lt;li&gt;have the elements of each block’s sub-sequence placed in that block as children,&lt;/li&gt;
  &lt;li&gt;look for the other blocks to process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-recursive-algorithm&quot;&gt;The recursive algorithm&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/img/zipper/recursion.png&quot; alt=&quot;Recursion&quot; title=&quot;From XKCD&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Supposing that we already have the full sequence of data available when we want
to process it, we could recursively build our tree by iterating on the sequence
in this way:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-clojure&quot;&gt;(defn build-tree [data-sequence]
  (letfn [;; Returns [built-children unconsumed-sequence]
          (append-children [children [element &amp;amp; next-sequence :as data-sequence]]
            ;; End of the tree construction.
            (if (nil? data-sequence)
              [children nil]

              (case (:type element)
                ;; If we need to open a new block.
                (:todo-list :url-list)
                (let [[sub-node-children unconsumed-sequence]
                      (append-children [] next-sequence)]
                  (append-children (conj children (assoc element :children sub-node-children))
                                   unconsumed-sequence))

                ;; If we need to close the current block.
                (:todo-list-end :url-list-end)
                [children next-sequence]

                ;; If we want to add a leaf node to the tree.
                (append-children (conj children element) next-sequence))))]

    (first (append-children [] data-sequence))))

;; Transforms the sequence into a tree.
(build-tree elements)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That implementation is hard to understand simply because
it does too many things at the same time:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Build a tree, nodes and children.&lt;/li&gt;
  &lt;li&gt;Keeps track of where we are in the sequence, &lt;strong&gt;in and out&lt;/strong&gt; of recursive calls.&lt;/li&gt;
  &lt;li&gt;Iterate on the sequence and handle termination.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also has limitations:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Messy code flow, hard to read and maintain with &lt;strong&gt;3 different recursion calls&lt;/strong&gt;
combined in a complicated way.&lt;/li&gt;
  &lt;li&gt;Does not check the match between elements like &lt;code&gt;:url-list&lt;/code&gt; and &lt;code&gt;:url-list-end&lt;/code&gt;,
would need an additional parameter for that (sigh!).&lt;/li&gt;
  &lt;li&gt;Not an incremental algorithm.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That type of recursive function takes a lot of time to write and debug.
It is not good for its writer, and it is not good for the co-workers who
have to read it at some point later in the future.&lt;/p&gt;

&lt;p&gt;We certainly can - and therefore we &lt;strong&gt;should&lt;/strong&gt; - do better.&lt;/p&gt;

&lt;h2 id=&quot;improvements&quot;&gt;Improvements&lt;/h2&gt;

&lt;p&gt;Important observation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The tree is being built at the same time than the data-sequence is being read.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of organizing the tree’s construction around the shape of
the tree, we could organize it around the shape of the sequence. After all,
thinking linearly is way more easy than thinking on a tree.&lt;/p&gt;

&lt;p&gt;The idiomatic way to process sequences in Clojure is to use the
&lt;a href=&quot;http://clojuredocs.org/clojure.core/reduce&quot;&gt;reduce&lt;/a&gt; operation.
For building our tree, it would look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-clojure&quot;&gt;(reduce (fn [tree data-element]
          ;; Add the element to the existing tree, return the updated-tree.
          (some-magic tree data-element))
        empty-tree
        data-sequence)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once we have an algorithm that updates the tree in a reducing process,
we know that our algorithm is incremental, as the reduce function is
an incremental process.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-clojure&quot;&gt;(reduce f :init [1 2 3])

;; The above can be rewritten as:
(-&amp;gt; :init
    (f 1)  ; process one data
    (f 2)  ; process another data
    (f 3)) ; and so on, and so on
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;the-incremental-algorithm&quot;&gt;The incremental algorithm&lt;/h2&gt;

&lt;p&gt;We need to replace the &lt;code&gt;some-magic&lt;/code&gt; function above with some real code.
Since we don’t have magic, let’s compensate using analytical thinking.&lt;/p&gt;

&lt;h3 id=&quot;tracking-the-node-to-edit&quot;&gt;Tracking the node to edit&lt;/h3&gt;

&lt;p&gt;Adding an element to a tree is easy, but knowing where to add it is not trivial.
The recursive algorithm knew where to add them because it implicitly kept track
of the node being currently edited.&lt;/p&gt;

&lt;p&gt;To emulate this, we need to &lt;strong&gt;keep track of that node&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;i-am-your-father&quot;&gt;“I am your father”&lt;/h3&gt;

&lt;p&gt;A shortcoming of the recursive algorithm was that there was no easy way to access
the other existing nodes of the tree being built.&lt;/p&gt;

&lt;p&gt;Ideally, it would be nice for the &lt;strong&gt;whole tree to be accessible&lt;/strong&gt; at any time,
specially &lt;strong&gt;the nodes close to the node been edited&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-zipper-solution&quot;&gt;The zipper solution&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/img/zipper/zipper.jpg&quot; alt=&quot;&quot; title=&quot;Zipper, photo by https://www.flickr.com/photos/southpaw2305/&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Zippers have both of the features above:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;They keep track of a tree structure and a current location in that tree.&lt;/li&gt;
  &lt;li&gt;They provide an access to the whole tree at any time of the editing,
from the node being tracked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is how the whole function looks like using a zipper:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-clojure&quot;&gt;(require '[clojure.zip :as z])

(defn build-tree [data-sequence]
  (let [;; Build a custom zipper
        empty-tree-zipper
        (z/zipper (comp #{:root :todo-list :url-list} :type)  ; branch?
                  :children                                   ; children
                  (fn [node children]                         ; make-node
                    (assoc node :children (vec children)))
                  {:type :root})                              ; root

        ;; The incremental update function
        update-zipper
        (fn [zipper element]
          (case (:type element)
            (:todo-list :url-list) (-&amp;gt; zipper
                                       (z/append-child element)
                                       (z/down)
                                       (z/rightmost))
            (:todo-list-end :url-list-end) (z/up zipper)
            (z/append-child zipper element)))]

    ;; Process the whole sequence
    (-&amp;gt; (reduce update-zipper
                empty-tree-zipper
                data-sequence)

        ;; Return the tree data structure from the zipper
        z/root)))

(build-tree elements)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Noteworthy:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code&gt;update-zipper&lt;/code&gt; function is the most important part,
it only take 8 lines of code and takes about 15 seconds to read and understand it.&lt;/li&gt;
  &lt;li&gt;Modifying the code to check for matching open/close elements is trivial and is
left to the reader as an exercise.&lt;/li&gt;
  &lt;li&gt;The function that manipulates the tree only do that, the function that defines
how to update node’s children is defined elsewhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;whats-next&quot;&gt;What’s next&lt;/h1&gt;

&lt;p&gt;In the next article, I will talk about a real life problem where a tree needed
to be built, and which was solved elegantly by using a custom zipper.&lt;/p&gt;</content><author><name>Vincent Cantin</name></author><category term="Clojure" /><category term="Clojure" /><category term="Data-structure" /><category term="Zipper" /><summary type="html">In his blog post and video from november 2018, Arne Brasseur explains the idea behind the functional zippers in the clojure.zip namespace. He describes how to use them to navigate existing tree-shaped data structures and how to modify them.</summary></entry><entry><title type="html">Build Your Own Transducer and Impress Your Cat - Part 5</title><link href="https://vincent.404.taipei/clojure/build-your-own-transducer-part5/" rel="alternate" type="text/html" title="Build Your Own Transducer and Impress Your Cat - Part 5" /><published>2018-05-21T00:00:00+00:00</published><updated>2018-05-21T00:00:00+00:00</updated><id>https://vincent.404.taipei/clojure/build-your-own-transducer-part5</id><content type="html" xml:base="https://vincent.404.taipei/clojure/build-your-own-transducer-part5/">&lt;p&gt;This post is a part of a serie:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part1/&quot;&gt;Introduction to transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part2/&quot;&gt;Anatomy of a transducer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part3/&quot;&gt;Stateful transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part4/&quot;&gt;Early termination in transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Functions which are using transducers (this post)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/green-coder/transducer-exercises&quot;&gt;Transducer exercises and solutions&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;This article describes some functions which are using transducers, and how to write your own.&lt;/p&gt;

&lt;h1 id=&quot;transducers-getting-into-using-them&quot;&gt;Transducers, getting &lt;code&gt;into&lt;/code&gt; using them&lt;/h1&gt;

&lt;p&gt;If you followed the previous 4 parts of this blog serie, you may have noticed that I only mentioned one function which is using transducers so far: the &lt;code&gt;into&lt;/code&gt; function.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(into [] (map inc) (list 3 4 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There are more of that kind. Their role is to provide the context of a stream transformation. This includes to &lt;strong&gt;provide a data stream&lt;/strong&gt; to the transducer, and to &lt;strong&gt;deal with the transformed stream&lt;/strong&gt; that they get from the transducer.&lt;/p&gt;

&lt;p&gt;They are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the &lt;code&gt;from where&lt;/code&gt; and the &lt;code&gt;to where&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;the &lt;code&gt;how do I take that input&lt;/code&gt; and the &lt;code&gt;what should I do with that output&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And since they are the one which are calling the transducer, they are also in charge of deciding the &lt;code&gt;when do I do this to that&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;transducer-users-from-the-standard-library&quot;&gt;Transducer users from the standard library&lt;/h3&gt;

&lt;p&gt;Note: In the following paragraph, the parameter &lt;code&gt;xform&lt;/code&gt; refers to a transducer.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://clojuredocs.org/clojure.core/into&quot;&gt;(into to xform from)&lt;/a&gt;: When you want the output stream’s elements to be all stored in a collection, which can be a vector, a list, a map, a sorted map, or any other type of other collection. I love that function because it appends to the collection &lt;a href=&quot;https://github.com/clojure/clojure/blob/clojure-1.9.0/src/clj/clojure/core.clj#L6820&quot;&gt;in a very efficient way&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://clojuredocs.org/clojure.core/sequence&quot;&gt;(sequence xform coll)&lt;/a&gt;: When you want the stream to be processed “only when needed”. Useful if you think that the sequence consumer may not need all the output elements, or if don’t want all of it to be processed immediately. That’s useful for throttling the transformation w.r.t. the CPU workload, or if you need to send the output stream over a slower channel like the network and you don’t want to buffer the whole output stream in advance.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://clojuredocs.org/clojure.core/eduction&quot;&gt;(eduction xform* coll)&lt;/a&gt;: … it’s complicated, see the docs for a precise explanation. Rarely needed by the average programmer. It returns a non-lazy sequence which is evaluated using the transducers each time it is being used by a &lt;a href=&quot;http://clojuredocs.org/clojure.core/reduce&quot;&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://clojuredocs.org/clojure.core/transduce&quot;&gt;(transduce xform f init coll)&lt;/a&gt;: When you want to use the &lt;a href=&quot;http://clojuredocs.org/clojure.core/reduce&quot;&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; operation but you also want to perform a stream transformation on the data to be reduced.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;transducer-users-from-the-clojurecoreasync-library&quot;&gt;Transducer users from the &lt;code&gt;clojure.core.async&lt;/code&gt; library&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://clojuredocs.org/clojure.core.async/chan&quot;&gt;(chan buf-or-n xform)&lt;/a&gt;: Creates a channel where the data stream on the reader side will be the one of the writer side transformed by the transducer.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://clojuredocs.org/clojure.core.async/pipeline&quot;&gt;(pipeline n to xf from)&lt;/a&gt;: “Takes elements from the from channel and supplies them to the to channel, subject to the transducer xf, with parallelism n […]”. To be used only with stateless transducers. Has the &lt;a href=&quot;http://clojuredocs.org/clojure.core.async/pipeline-blocking&quot;&gt;&lt;code&gt;pipeline-blocking&lt;/code&gt;&lt;/a&gt; variant.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://clojuredocs.org/clojure.core.async/transduce&quot;&gt;(transduce xform f init ch)&lt;/a&gt;: A variant of &lt;a href=&quot;http://clojuredocs.org/clojure.core/transduce&quot;&gt;&lt;code&gt;clojure.core/transduce&lt;/code&gt;&lt;/a&gt; where the data stream comes from a channel instead of a collection.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;other-uses-of-transducers&quot;&gt;Other uses of transducers&lt;/h3&gt;

&lt;p&gt;There may be other functions that use transducers, adapted to different contexts. If you know some, please let me know by leaving a comment and I will add them if they are relevant to the audience.&lt;/p&gt;

&lt;h1 id=&quot;lets-implement-some&quot;&gt;Let’s implement some!&lt;/h1&gt;

&lt;p&gt;Good news, transducers are now your friends, you can call them when you want. But if you want to be a good friend, there are some rules to follow.&lt;/p&gt;

&lt;h3 id=&quot;the-output-function&quot;&gt;The output function&lt;/h3&gt;

&lt;p&gt;Transducers are technically functions which transform a reducing function into another reducing function.&lt;/p&gt;

&lt;p&gt;If you don’t know what that mean, you can also see them as a functions that transform a kind of output function into another one, except that this output function is taking a kind of accumulator value as its first parameter.&lt;/p&gt;

&lt;p&gt;Let’s play with this idea a bit and let’s implement a function that provides a stream of data from a collection to a transducer and outputs the transformed stream to the standard output, element by element.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;; Notes:
; - Don't use this at home, this is still a toy function.
; - The transducer is commonly called 'xf' and the reducing function 'rf'.
(defn print-duce [transducer coll]
  (let [reducing-fn #(print (str %2 &quot; &quot;))
        process (transducer reducing-fn)]
    (loop [c coll]
      (when (seq c)
        (process nil (first c))
        (recur (rest c))))))

(print-duce (map inc) (list 3 4 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;; However the following does not work, there is a bug in print-duce:
; the [5] is missing!
(print-duce (partition-all 2) (list 3 4 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;0-1-2-arity&quot;&gt;{0 1 2}-Arity&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/img/xf-tuto/arrietty.jpg&quot; alt=&quot;You said Arrietty?&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you read the parts 1 to 4 of this blog serie, you will know that transducers are expected to be called with different arities.&lt;/p&gt;

&lt;p&gt;0-Arity: &lt;strong&gt;Just ignore it&lt;/strong&gt;, don’t call it unless you know what you are doing (and let me know why in the comments or &lt;a href=&quot;https://stackoverflow.com/questions/48848876/transducers-init-not-called&quot;&gt;in that StackOverflow question&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;2-Arity: Call it each time you want &lt;strong&gt;to feed one more data element to the transducer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;1-Arity: Call it once you to inform that there are no inputs available anymore. The transducer (even a stateless one) &lt;strong&gt;may flush a few more data&lt;/strong&gt; to your output function.&lt;/p&gt;

&lt;p&gt;Now let’s improve our &lt;code&gt;print-ducer&lt;/code&gt; a bit.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;; Note: Still a toy function.
(defn print-duce [xf coll]
  (let [rf (fn ([])
               ([result] (print &quot;\n--EOS&quot;))
               ([result input] (print (str input &quot; &quot;))))
        process (xf rf)]
    (loop [c coll]
      (if (seq c)
        (do
          (process nil (first c)) ; 2-arity 'process'
          (recur (rest c)))
        (process nil)))))         ; 1-arity 'flush'

(print-duce (map inc) (list 3 4 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;; Now this works, [5] is not missing:
(print-duce (partition-all 2) (list 3 4 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;enough-is-enough-early-termination&quot;&gt;Enough is enough (early termination)&lt;/h3&gt;

&lt;p&gt;Your transducer has its say on when to stop the stream. It will return a &lt;code&gt;reduced&lt;/code&gt; value when it thinks that there should not be any other element. You need to pay attention to it and not ask too much.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn print-duce [xf coll]
  (let [rf (fn ([])
               ([result] (print &quot;\n--EOS&quot;))
               ([result input] (print (str input &quot; &quot;))))
        process (xf rf)]
    (loop [c coll]
      (if (seq c)
        (let [result (process nil (first c))]
          (if (reduced? result)
            (process (deref result)) ; unwraps it and stop processing the stream
            (recur (rest c))))       ; continue processing the stream
        (process nil)))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that I used &lt;code&gt;deref&lt;/code&gt; in order to unwrap the reduced value while I was using &lt;code&gt;unreduced&lt;/code&gt; in the part 4. Those two functions are different, &lt;code&gt;deref&lt;/code&gt; really does unwrap the reduced value, and &lt;a href=&quot;http://clojuredocs.org/clojure.core/unreduced&quot;&gt;&lt;code&gt;unreduced&lt;/code&gt;&lt;/a&gt; is unwrapping a value &lt;strong&gt;only if&lt;/strong&gt; it is reduced.&lt;/p&gt;

&lt;p&gt;Source code:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-clojure&quot;&gt;(defn unreduced [x]
  (if (reduced? x) (deref x) x))
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;reduce-function-as-a-parameter&quot;&gt;Reduce function as a parameter&lt;/h3&gt;

&lt;p&gt;What if we want to make our function more general and accept a “1-and-2-arity” reducing function as a parameter?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn multi-duce [xf rf init coll]
  (let [process (xf rf)]
    (loop [acc init
           c coll]
      (if (seq c)
        (let [result (process acc (first c))]
          (if (reduced? result)
            (process (deref result))
            (recur result (rest c))))
        (process acc)))))

(multi-duce (map inc) conj [] (list 3 4 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(multi-duce (partition-all 2) conj [] (list 3 4 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;easy-made-simple-by-my-cat&quot;&gt;Easy made simple (by my cat)&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/img/xf-tuto/dilbert.jpg&quot; alt=&quot;This is not my cat&quot; /&gt;&lt;/p&gt;

&lt;p&gt;My cat just told me that I am an idiot as there is a shorter and more efficient way to implement the function above.&lt;/p&gt;

&lt;p&gt;I gave the keyboard to him and here is what he shown me:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn cat-duce [xf rf init coll]
  (let [process (xf rf)
        result (reduce process init coll)]
      (process result)))

(cat-duce (map inc) conj [] (list 3 4 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(cat-duce (partition-all 2) conj [] (list 3 4 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Indeed, it seems to work. Thank you cat!&lt;/p&gt;

&lt;h3 id=&quot;the-transduce-function&quot;&gt;The &lt;code&gt;transduce&lt;/code&gt; function&lt;/h3&gt;

&lt;p&gt;The cat-duce function is very close to the implementation of the legendary &lt;a href=&quot;http://clojuredocs.org/clojure.core/transduce&quot;&gt;&lt;code&gt;transduce&lt;/code&gt;&lt;/a&gt; function. It has the same signature and &lt;a href=&quot;https://github.com/clojure/clojure/blob/clojure-1.9.0/src/clj/clojure/core.clj#L6800&quot;&gt;almost the same implementation&lt;/a&gt;, the difference being the added support for collections which want to be noticed when they are being reduced (like the result of the &lt;a href=&quot;http://clojuredocs.org/clojure.core/eduction&quot;&gt;&lt;code&gt;eduction&lt;/code&gt;&lt;/a&gt; function).&lt;/p&gt;

&lt;h1 id=&quot;whats-next&quot;&gt;What’s next&lt;/h1&gt;

&lt;p&gt;Congratulations !!!&lt;/p&gt;

&lt;p&gt;By now you should probably know anything you need to use the transducers in your own custom way. You may still need to exercise your skills a little bit - &lt;strong&gt;Practice makes perfect&lt;/strong&gt;.&lt;/p&gt;

&lt;iframe width=&quot;755&quot; height=&quot;566&quot; src=&quot;https://www.youtube.com/embed/04854XqcfCY&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;I am going to publish some transducer-related exercises on May 30th 2018 to be used as a support for a &lt;a href=&quot;https://clojure.tw/weekly/2018-05-20/&quot;&gt;transducer workshop in Taipei&lt;/a&gt;. The link will be added here soon after.&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: I created a Github project with some &lt;a href=&quot;https://github.com/green-coder/transducer-exercises&quot;&gt;transducer exercises and their solutions&lt;/a&gt;, feel free to give it a try and let me know if it helped.&lt;/p&gt;</content><author><name>Vincent Cantin</name></author><category term="Clojure" /><category term="Clojure" /><category term="Transducer" /><category term="Beginners" /><summary type="html">This post is a part of a serie:</summary></entry><entry><title type="html">Build Your Own Transducer and Impress Your Cat - Part 4</title><link href="https://vincent.404.taipei/clojure/build-your-own-transducer-part4/" rel="alternate" type="text/html" title="Build Your Own Transducer and Impress Your Cat - Part 4" /><published>2018-05-13T00:00:00+00:00</published><updated>2018-05-13T00:00:00+00:00</updated><id>https://vincent.404.taipei/clojure/build-your-own-transducer-part4</id><content type="html" xml:base="https://vincent.404.taipei/clojure/build-your-own-transducer-part4/">&lt;p&gt;This post is a part of a serie:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part1/&quot;&gt;Introduction to transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part2/&quot;&gt;Anatomy of a transducer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part3/&quot;&gt;Stateful transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Early termination in transducers (this post)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part5/&quot;&gt;Functions which are using transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/green-coder/transducer-exercises&quot;&gt;Transducer exercises and solutions&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;early-termination-and-reduced-values-in-transducers&quot;&gt;Early termination and &lt;code&gt;reduced?&lt;/code&gt; values in transducers&lt;/h1&gt;

&lt;p&gt;Suppose that you want to write a transducer that uses some of the elements in the input stream and then ignore anything after it. It would be a waste to have to iterate on the remaining values of the stream if we do not use them.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn tired-map-transducer [func energy tired-answer]
  (fn [rf]
    (let [state (volatile! energy)]
      (fn ([] (rf))
          ([result] (rf result))
          ([result input]
           (rf result
               (let [energy @state]
                 (if (pos? energy)
                   (do
                     (vreset! state (dec energy))
                     (func input))
                   tired-answer))))))))

(into []
      (tired-map-transducer inc 5 :whatever)
      (list 1 2 3 4 5 6 7 8 9 10))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We certainly want to find a way to let the function calling the transducers to stop calling them.&lt;/p&gt;

&lt;p&gt;We could do that in multiple ways, like sending a special value &lt;code&gt;:enough&lt;/code&gt; after the last data. But what if that special data &lt;code&gt;:enough&lt;/code&gt; appears in some input data stream? Sending it to the output would be misleadingly interpreted as the transducer’s message to early terminate.&lt;/p&gt;

&lt;p&gt;The Clojure core team came up with something that is very unlikely to appear in the input data stream by luck (or we could call it a bug and blame the user instead :-) ), and established it as a convention for transducers to inform their calling function about a value being the last one their would like to return.&lt;/p&gt;

&lt;p&gt;That convention is: &lt;code&gt;(reduced last-value)&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn responsible-map-transducer [func energy]
  (fn [rf]
    (let [state (volatile! energy)]
      (fn ([] (rf))
          ([result] (rf result))
          ([result input]
           (let [energy @state]
             (vreset! state (dec energy))
             (cond-&amp;gt; (rf result (func input))
               (&amp;lt;= energy 1) reduced)))))))

(into []
      (responsible-map-transducer inc 5)
      (list 1 2 3 4 5 6 7 8 9 10))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;reduced&lt;/code&gt; is simply returning a wrapped value. A value can be tested by the calling function as being wrapped or not by using the predicate &lt;code&gt;reduced?&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(reduced? 7)
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(reduced? (reduced 7))
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;are-we-done-then&quot;&gt;Are we done, then?&lt;/h2&gt;

&lt;p&gt;There is one more thing to check before calling it done.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/xf-tuto/train-hide-other-train.jpg&quot; alt=&quot;Look both ways when crossing the railway.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s test our transducer a little more. Is it still going to work in those cases?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-clojure&quot;&gt;(into []
      (comp
        (responsible-map-transducer inc 5)  ; Step 1
        (responsible-map-transducer inc 3)) ; Step 2
      (list 1 2 3 4 5 6 7 8 9 10))
; =&amp;gt; [3 4 5]
; It works fine.

(into []
      (comp
        (responsible-map-transducer inc 3)  ; Step 1
        (responsible-map-transducer inc 5)) ; Step 2
      (list 1 2 3 4 5 6 7 8 9 10))
; =&amp;gt; [3 4 5]
; It works fine.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It all works fine. So why did I ask? Because you have to know why it still works.&lt;/p&gt;

&lt;p&gt;The implementation of &lt;code&gt;responsible-map-transducer&lt;/code&gt; only took care of what it returns when it has no energy. Nothing special was done with the result of &lt;code&gt;(rf result ...)&lt;/code&gt; in the normal case, it was simply returned as is. If it was a &lt;code&gt;reduced?&lt;/code&gt; value, it means that the &lt;code&gt;rf&lt;/code&gt; function wanted an early termination. Our transducer has to make sure that in this case the returned value is &lt;code&gt;reduced&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It happens to be the case here because we simply returned what the &lt;code&gt;rf&lt;/code&gt; function returned, so we are in luck. This may not always be the case, so always pay attention and watch in both ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Handle the case where your transducer wants an early termination,&lt;/li&gt;
  &lt;li&gt;Handle the case where &lt;code&gt;rf&lt;/code&gt; wants an early termination.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-devil-is-in-the-details&quot;&gt;The devil is in the details&lt;/h2&gt;

&lt;p&gt;Did you think about testing that?&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(into []
      (comp
        (responsible-map-transducer inc 3)  ; Step 1
        (responsible-map-transducer inc 3)) ; Step 2
      (list 1 2 3 4 5 6 7 8 9 10))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You didn’t? Too bad because you should have: It triggers a bug and you get an extremely unclear error message now.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/xf-tuto/confused-baby.jpg&quot; alt=&quot;Confused Baby&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Something happened when we returned a value which was wrapped at the same time by both transducers: &lt;code&gt;(reduced (reduced last-value))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The function which is calling the transducers (i.e. &lt;code&gt;into&lt;/code&gt;) is supporting early termination by expecting either a value or a &lt;code&gt;reduced&lt;/code&gt; value, in which case it is getting the unwrapped value via &lt;code&gt;(unreduced reduced-value)&lt;/code&gt;. But instead of getting the value, it still gets a reduced value.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(reduced? (unreduced (reduced (reduced 7))))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;How to fix it? Either we ask the Clojure core team to change all the functions which are using transducers to support multi-wrapped values, or either we avoid wrapping the values more than once.&lt;/p&gt;

&lt;h2 id=&quot;there-is-a-function-for-that--rich-hickey&quot;&gt;“There is a function for that” — Rich Hickey&lt;/h2&gt;

&lt;p&gt;We can use the function &lt;a href=&quot;http://clojuredocs.org/search?q=ensure-reduced&quot;&gt;&lt;code&gt;ensure-reduced&lt;/code&gt;&lt;/a&gt; from the standard library. Its implementation is very simple:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn ensure-reduced [x]
  (if (reduced? x) x (reduced x)))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now let’s correct our transducer.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn correct-map-transducer [func energy]
  (fn [rf]
    (let [state (volatile! energy)]
      (fn ([] (rf))
          ([result] (rf result))
          ([result input]
           (let [energy @state]
             (vreset! state (dec energy))
             (cond-&amp;gt; (rf result (func input))
               (&amp;lt;= energy 1) ensure-reduced))))))) ; &amp;lt;- The difference is here

(into []
      (comp
        (correct-map-transducer inc 3)  ; Step 1
        (correct-map-transducer inc 3)) ; Step 2
      (list 1 2 3 4 5 6 7 8 9 10))

; Idiomatic way:
; (into []
;       (comp
;         (take 3)   ; Step 1
;         (map inc)  ; Step 2
;         (map inc)) ; Step 3
;       (range 1 11))

;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;You already know everything you need to implement your own transducers. I encourage you to try some ideas on your own. If you encounter blocking problems in your adventure, feel free to leave a comment and I will try to help you (when I have time).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part5/&quot;&gt;In the next part&lt;/a&gt;, I talk about functions like &lt;code&gt;into&lt;/code&gt; which are &lt;strong&gt;using&lt;/strong&gt; the transducers and how to write one.&lt;/p&gt;</content><author><name>Vincent Cantin</name></author><category term="Clojure" /><category term="Clojure" /><category term="Transducer" /><category term="Beginners" /><summary type="html">This post is a part of a serie:</summary></entry><entry><title type="html">Build Your Own Transducer and Impress Your Cat - Part 3</title><link href="https://vincent.404.taipei/clojure/build-your-own-transducer-part3/" rel="alternate" type="text/html" title="Build Your Own Transducer and Impress Your Cat - Part 3" /><published>2018-05-12T00:00:00+00:00</published><updated>2018-05-12T00:00:00+00:00</updated><id>https://vincent.404.taipei/clojure/build-your-own-transducer-part3</id><content type="html" xml:base="https://vincent.404.taipei/clojure/build-your-own-transducer-part3/">&lt;p&gt;This post is a part of a serie:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part1/&quot;&gt;Introduction to transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part2/&quot;&gt;Anatomy of a transducer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Stateful transducers (this post)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part4/&quot;&gt;Early termination in transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part5/&quot;&gt;Functions which are using transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/green-coder/transducer-exercises&quot;&gt;Transducer exercises and solutions&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;stateful-transducers&quot;&gt;Stateful transducers&lt;/h1&gt;

&lt;p&gt;This article describes briefly how to implement a stateful transducer.&lt;/p&gt;

&lt;h2 id=&quot;when-do-we-need-them&quot;&gt;When do we need them&lt;/h2&gt;

&lt;p&gt;We need them each time some output elements depend on multiple input elements.&lt;/p&gt;

&lt;p&gt;Some information related to previous input values need to be stored until the transducer has enough of them to start outputting values.&lt;/p&gt;

&lt;p&gt;The information stored could simply be the input values, or it could be a derived information (which usually takes less space in memory).&lt;/p&gt;

&lt;h2 id=&quot;stringifier-transducer&quot;&gt;Stringifier Transducer&lt;/h2&gt;

&lt;p&gt;Suppose that we have a stream of chars representing zero terminated strings and we want to have a stream of strings.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn string-builder-transducer [separator]
  ; The local state *should not* be defined here.
  (fn [rf]
    ; The local state of the transducer comes here.
    (let [state (volatile! [])]
      (fn ([] (rf))
          ([result] (-&amp;gt; result
                        (rf (apply str @state))
                        (rf)))
          ([result input]
           (let [chars @state]
             (if (= separator input)
               (do (vreset! state [])
                   (rf result (apply str chars)))
               (do (vreset! state (conj chars input))
                   result))))))))

(into []
      (string-builder-transducer 0)
      (list \H \e \l \l \o 0 \C \l \o \j \u \r \e 0 \w \o \r \l \d \!))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Three notes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The position where the local state should be introduced matters. If you introduce it at the wrong place, some local state will linger when the transducer is used in multiple pipelines and cause bugs.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;volatile!&lt;/code&gt; and &lt;code&gt;vreset!&lt;/code&gt; are used instead of atoms for efficiency.&lt;/li&gt;
  &lt;li&gt;In this example, the transducer simply stores the encountered chars until the end of each chunk and then used them all at once to create a string. It does not have to always be this way (e.g. the next paragraph).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;chunk-sum-transducer&quot;&gt;Chunk Sum Transducer&lt;/h2&gt;

&lt;p&gt;Suppose that we have a stream of numbers separated by a special keyword &lt;code&gt;:|&lt;/code&gt; and we want to compute the sum of each chunk of numbers.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn chunk-sum-transducer [separator]
  (fn [rf]
    (let [state (volatile! 0)]
      (fn ([] (rf))
          ([result] (-&amp;gt; result
                        (rf @state)
                        (rf)))
          ([result input]
           (let [acc @state]
             (if (= separator input)
               (do (vreset! state 0)
                   (rf result acc))
               (do (vreset! state (+ acc input))
                   result))))))))

(into []
      (chunk-sum-transducer :|)
      (list 1 2 3 4 :| 42 :| :| 3 5))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that our transducer is efficient in terms of memory as it only keep a sum of numbers in its local state instead of all the elements of the current chunk.&lt;/p&gt;

&lt;h2 id=&quot;packet-transducer&quot;&gt;Packet Transducer&lt;/h2&gt;

&lt;p&gt;Another example a little more complex, this transducer groups messages together in packets of data so that the size of the packet does not exceed its maximum limit (if possible, otherwise it uses bigger packets).&lt;/p&gt;

&lt;p&gt;Here we use a map containing multiple values as the local state.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn packet-transducer [max-size]
  (fn [rf]
    (let [state (volatile! {:packet []
                            :size 0})]
      (fn ([] (rf))
          ([result]
           (let [{:keys [packet size]} @state]
             (cond-&amp;gt; result
                     (pos? size) (rf packet) ; Flush the local state to output.
                     :always (rf))))         ; Transmit the flush signal.
          ([result input]
           (let [{:keys [packet size]} @state
                 input-size (count input)
                 new-size (+ size input-size)]
             (if (&amp;lt;= new-size max-size)
               (do (vreset! state {:packet (conj packet input)
                                   :size new-size})
                   result)
               (do (vreset! state {:packet [input]
                                   :size input-size})
                   (cond-&amp;gt; result
                           (pos? size) (rf packet))))))))))

(into []
      (packet-transducer 5)
      (list [1 1] [2 2] [3 3 3] [4 4] [5] [6 6 6 6 6]))
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part4/&quot;&gt;In the next part of this blog serie&lt;/a&gt;, I talk about how to support early termination in a data pipeline by using &lt;code&gt;reduced&lt;/code&gt; and &lt;code&gt;reduced?&lt;/code&gt;.&lt;/p&gt;</content><author><name>Vincent Cantin</name></author><category term="Clojure" /><category term="Clojure" /><category term="Transducer" /><category term="Beginners" /><summary type="html">This post is a part of a serie:</summary></entry><entry><title type="html">Build Your Own Transducer and Impress Your Cat - Part 2</title><link href="https://vincent.404.taipei/clojure/build-your-own-transducer-part2/" rel="alternate" type="text/html" title="Build Your Own Transducer and Impress Your Cat - Part 2" /><published>2018-05-10T00:00:00+00:00</published><updated>2018-05-10T00:00:00+00:00</updated><id>https://vincent.404.taipei/clojure/build-your-own-transducer-part2</id><content type="html" xml:base="https://vincent.404.taipei/clojure/build-your-own-transducer-part2/">&lt;p&gt;This post is a part of a serie:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part1/&quot;&gt;Introduction to transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Anatomy of a transducer (this post)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part3/&quot;&gt;Stateful transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part4/&quot;&gt;Early termination in transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part5/&quot;&gt;Functions which are using transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/green-coder/transducer-exercises&quot;&gt;Transducer exercises and solutions&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;anatomy-of-a-transducer&quot;&gt;Anatomy of a transducer&lt;/h1&gt;

&lt;p&gt;This article describes briefly the structure of a transducer and how to implement one.&lt;/p&gt;

&lt;h2 id=&quot;simple-one-one-mapping&quot;&gt;Simple one-one mapping&lt;/h2&gt;

&lt;p&gt;Let’s suppose that we want to manually create a transducer that increments numbers. We could normally just use &lt;code&gt;(map inc)&lt;/code&gt;, but for the training we will do it from scratch.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(def inc-transducer
  (fn [rf]
    (fn ([] (rf))                                   ; 0-arity aka 'the useless'
        ([result] (rf result))                      ; 1-arity aka 'the flusher'
        ([result input] (rf result (inc input)))))) ; 2-arity aka 'the doer'

(into [] inc-transducer (list 4 5 6))

; idiomatic way:
; (into [] (map inc) (list 4 5 6))

;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;rf&lt;/code&gt; function is processing the output value of our transducer. It does … ‘something’ to return a merged (or not) version of the &lt;code&gt;result&lt;/code&gt; value with the processed data’s value &lt;code&gt;(inc input)&lt;/code&gt;, and our transducer needs to return that new result.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;rf&lt;/code&gt; function could be just another transducer which we composed with, or it could be a terminal reducing function (hence the name &lt;code&gt;rf&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;0-arity&lt;/code&gt; function is (IHMO) a useless bogus convention as we cannot rely on it being called for sure by the functions which use transducers. Just transmit the call to the next transducer/rf, maybe it will do something with it in some specific context, who knows.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;1-arity&lt;/code&gt; function is called by the function who uses the transducer when there is no more data to be processed. That’s where transducers can flush their data if they had some in a local state (more on this possibility later).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;2-arity&lt;/code&gt; is where the input data gets processed and passed to the next function in the pipeline.&lt;/p&gt;

&lt;h2 id=&quot;one-one-mapping-with-parameters&quot;&gt;One-one mapping with parameters&lt;/h2&gt;

&lt;p&gt;Now let’s suppose that instead of incrementing the numbers we want to add them a given value, then we need a transducer with a parameter.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn add-transducer [n]
  (fn [rf]
    (fn ([] (rf))
        ([result] (rf result))
        ([result input] (rf result (+ input n))))))

(into [] (add-transducer 3) (list 4 5 6))

; idiomatic way:
; (into [] (map #(+ 3 %)) (list 4 5 6))

;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;no-rabbit-transducer-one-some&quot;&gt;No Rabbit transducer (One-Some)&lt;/h2&gt;

&lt;p&gt;We want a transducer that makes the rabbits disappear, to illustrate the case where the transducer may not provide a new output value.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn magician-transducer [animal]
  (fn [rf]
    (fn ([] (rf))
        ([result] (rf result))
        ([result input]
          (if (= animal input)
              result             ; Just don't &quot;merge&quot; the input into the result.
              (rf result input))))))

(into [] (magician-transducer :rabbit) (list :dog :rabbit :lynel))

; idiomatic ways:
; (into [] (remove #(= :rabbit %)) (list :dog :rabbit :lynel))
; (into [] (filter #(not= :rabbit %)) (list :dog :rabbit :lynel))

;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;No rabbit, no problem.&lt;/p&gt;

&lt;h2 id=&quot;more-cats-transducer-one-two&quot;&gt;More cats transducer (One-Two)&lt;/h2&gt;

&lt;p&gt;And what if we want more cats now? (more data output than input)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(defn glitch-transducer [animal]
  (fn [rf]
    (fn ([] (rf))
        ([result] (rf result))
        ([result input]
         (if (= animal input)
             (-&amp;gt; result
                 (rf input)
                 (rf input)) ; Send the input twice to the output pipeline.
             (rf result input))))))

(into [] (glitch-transducer :cat) (list :dog :cat :lynel))

; idiomatic way:
; (into []
;       (mapcat #(if (= :cat %) (list % %) (list %)))
;       (list :dog :cat :lynel))

;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;More cats. Neo would be happy.&lt;/p&gt;

&lt;h2 id=&quot;rle-decompression-one-many&quot;&gt;RLE decompression (One-Many)&lt;/h2&gt;

&lt;p&gt;Suppose that we want to send a serie of values in one go to the output but we can’t do it as in the previous example because the number of repeats is not fixed or is too big and we are lazy and sane. We can use &lt;code&gt;reduce&lt;/code&gt; to output the values one by one (now you can see why &lt;code&gt;rf&lt;/code&gt; is called like that, it can be seen as a reducing function).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(def rle-decoder-transducer
  (fn [rf]
    (fn ([] (rf))
        ([result] (rf result))
        ([result [count data]]
         (reduce rf result (repeat count data))))))

(into []
      rle-decoder-transducer
      (list [0 :a] [1 :b] [2 :c] [3 :d]))

; idiomatic way:
; (into []
;       (mapcat (fn [[count data]] (repeat count data)))
;       (list [0 :a] [1 :b] [2 :c] [3 :d]))

;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next&lt;/h2&gt;

&lt;p&gt;All the transducers shown above are &lt;strong&gt;stateless&lt;/strong&gt;: Their behavior is fully described by their inputs and their initial immutable parameters.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part3/&quot;&gt;In the next part of this blog post&lt;/a&gt;, I cover the &lt;strong&gt;stateful&lt;/strong&gt; transducers, those with a local mutable state.&lt;/p&gt;</content><author><name>Vincent Cantin</name></author><category term="Clojure" /><category term="Clojure" /><category term="Transducer" /><category term="Beginners" /><summary type="html">This post is a part of a serie:</summary></entry><entry><title type="html">Build Your Own Transducer and Impress Your Cat - Part 1</title><link href="https://vincent.404.taipei/clojure/build-your-own-transducer-part1/" rel="alternate" type="text/html" title="Build Your Own Transducer and Impress Your Cat - Part 1" /><published>2018-05-08T00:00:00+00:00</published><updated>2018-05-08T00:00:00+00:00</updated><id>https://vincent.404.taipei/clojure/build-your-own-transducer-part1</id><content type="html" xml:base="https://vincent.404.taipei/clojure/build-your-own-transducer-part1/">&lt;p&gt;This post is a part of a serie:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Introduction to transducers (this post)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part2/&quot;&gt;Anatomy of a transducer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part3/&quot;&gt;Stateful transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part4/&quot;&gt;Early termination in transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part5/&quot;&gt;Functions which are using transducers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/green-coder/transducer-exercises&quot;&gt;Transducer exercises and solutions&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;This article is a brief introduction to what transducers are and how to use them.&lt;/p&gt;

&lt;h1 id=&quot;hello-transduced-world&quot;&gt;Hello Transduced World&lt;/h1&gt;

&lt;p&gt;In simple words:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A transducer is the equivalent of an operation on a stream of data elements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That man is a kind of transducer, it takes data elements from its input and may send some on its output:
&lt;img src=&quot;/img/xf-tuto/human_resource_machine01.png&quot; alt=&quot;A kind of transducer&quot; title=&quot;from the game 'Human Resource Machine'&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can see it as a function which is called exactly once for each element of the input stream, and which can spit any number of elements to its output stream.&lt;/p&gt;

&lt;p&gt;There is a special emphasis on the fact that:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the transducer is not taking anything from the input stream by itself, it is not his job or responsibility. It gets called (by something else) with each data element.&lt;/li&gt;
  &lt;li&gt;the transducer only knows that it has to call a designated (and obscure) function with each of it output elements and has to return its result. It has no idea where the data goes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🤓 Note: &lt;em&gt;If you want to play at being yourself a transducer in a funny fictional world with an intuitive and simple programming syntax, &lt;a href=&quot;https://en.wikipedia.org/wiki/Human_Resource_Machine&quot;&gt;give this cool game a try&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;vincent-please-focus&quot;&gt;Vincent, please focus&lt;/h1&gt;

&lt;p&gt;Oh okay, right.&lt;/p&gt;

&lt;p&gt;Here is the simplest transducer:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-clojure&quot;&gt;(map identity)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It accepts some data elements as input and gives the exact same data elements to its output. Except that at the moment it has no friends, nobody gave him data and it was not provided an output. A transducer alone is like a stomach without food (hmm .. let’s not talk too much about the output in that case, but notice that it still needs a place to go).&lt;/p&gt;

&lt;p&gt;Let’s use that transducer properly. Here the &lt;code&gt;into&lt;/code&gt; function gives it some data elements from a list and collects its output elements into a vector.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(into [&quot;b&quot; &quot;a&quot;] (map identity) (list &quot;n&quot; &quot;a&quot; &quot;n&quot; &quot;a&quot;))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Another example with a transducer that actually does something with its input, it transforms each character into its preceding character in the alphabet.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(into [&quot;b&quot; &quot;a&quot;]
      (map #(char (dec (.charCodeAt % 0))))
      (list &quot;u&quot; &quot;n&quot; &quot;b&quot; &quot;o&quot;))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice that you can use any function &lt;code&gt;f&lt;/code&gt; which takes 1 value as parameter and returns 1 value by using the form &lt;code&gt;(map f)&lt;/code&gt;. Simple and easy.&lt;/p&gt;

&lt;p&gt;Now let’s see some built-in transducers which do not have the same number of input and output elements.&lt;/p&gt;

&lt;p&gt;This one outputs 1 or none output element for each input element:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(into []
      (filter #(&amp;lt;= (.charCodeAt &quot;a&quot; 0) (.charCodeAt % 0) (.charCodeAt &quot;f&quot; 0)))
      (list &quot;c&quot; &quot;r&quot; &quot;a&quot; &quot;f&quot; &quot;e&quot; &quot;b&quot; &quot;h&quot; &quot;a&quot; &quot;b&quot; &quot;l&quot; &quot;e&quot;))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This one gives 1 or more output elements for each input element.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(into []
      (mapcat #(if (&amp;lt;= 0 % 9)
                 (list % %)
                 (list %)))
      (list 10 5 16 7 13))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Notes: The function provided to &lt;code&gt;mapcat&lt;/code&gt; returns a collection of arbitrary size and &lt;code&gt;mapcat&lt;/code&gt; returns a transducer which outputs an arbitrary number of elements for each input element.&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;will-it-blend&quot;&gt;Will it blend?&lt;/h1&gt;

&lt;p&gt;Multiple transducers can be piped together to give birth to more complex data processing pipelines. This is done via the &lt;code&gt;comp&lt;/code&gt; function and the result of the composition is a transducer. The data elements flow one after another through the pipeline, no buffer is used for storing intermediary results between each of its steps - that’s a streaming process.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-eval-clojure&quot;&gt;(into []
      (comp
        (map inc)                 ; first step
        (filter odd?)             ; second step
        (mapcat #(if (&amp;lt;= 0 % 9)   ; third step
                   (list % %)
                   (list %))))
      (list 8 9 10 11 12))
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&quot;the-built-in-transducers&quot;&gt;The built-in transducers&lt;/h1&gt;

&lt;p&gt;Clojure has a few transducers which are very popular because they are handy.&lt;/p&gt;

&lt;p&gt;[TODO: insert a link to a post that my future self will write about it]&lt;/p&gt;

&lt;h1 id=&quot;whats-next&quot;&gt;What’s next&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;/clojure/build-your-own-transducer-part2/&quot;&gt;In the next post&lt;/a&gt;, I talk about the anatomy of a transducer and how to program your own.&lt;/p&gt;</content><author><name>Vincent Cantin</name></author><category term="Clojure" /><category term="Clojure" /><category term="Transducer" /><category term="Beginners" /><summary type="html">This post is a part of a serie:</summary></entry></feed>