Combined looping and recursion when implementing Quicksort, using proper Clojure style In "The Joy of Clojure", 2nd edition, code for quicksort is introduced on page 133 that I found hard to digest. I have rewritten it to make it clearer (at least to myself). 

Here is the original:

(defn sort-parts-joc [work]
  (lazy-seq
    (loop [[part &amp; parts] work]
      (if-let [[pivot &amp; xs] (seq part)]
        (let [smaller? #(&lt; % pivot)]
          (recur (list*
                  (filter smaller? xs)
                  pivot
                  (remove smaller? xs)
                  parts)))
        (when-let [[x &amp; parts] parts]
            (cons x (sort-parts-joc parts)))))))


Here is the rewritten code:

(defn sort-parts-explicit-lazy [work]
   (lazy-seq        
      (loop [loopwork work]
         (let [[ part &amp; partz ] loopwork ]
            (if-let [[pivot &amp; valuez] (seq part)]
                  (let [ smaller? #(&lt; % pivot)
                         smz      (filter smaller? valuez)
                         lgz      (remove smaller? valuez)
                         nxxt     (list* smz pivot lgz partz) ]
                        (recur nxxt))
                  (if-let [[oldpivot &amp; rightpartz] partz]
                          (cons oldpivot (sort-parts-explicit-lazy rightpartz))                    
                          []))))))


Testing:

(require '( clojure test ))
(clojure.test/is (is-sorted (sort-parts-explicit-lazy [[]])))
(clojure.test/is (is-sorted (sort-parts-explicit-lazy [[1]])))
(clojure.test/is (is-sorted (sort-parts-explicit-lazy [[1 2]])))
(clojure.test/is (is-sorted (sort-parts-explicit-lazy [[1 2 3]])))
(clojure.test/is (is-sorted (sort-parts-explicit-lazy [[3 2 1]])))
(clojure.test/is (is-sorted (sort-parts-explicit-lazy [[3 3 3]])))


So, it works. 

Both functions are essentially the same.

However I have a bad feeling about this. The simultaneous use of recur and full recursion, with the full recursion path "leaving" the loop in its middle in the same function feels weird, like unstructured code dropping a good, fat GOTO.

Here is the expression tree for reference:



We are far from from beta-reduction here. The "reduction" can only be understood using explicit instruction flow semantics. Okay, reality meets platonic ideals.

Is the loop-recur/full-recursion supposed to look like this? Is it a style problem that can be improved?
We are far from from beta-reduction here. The "reduction" can only be
  understood using explicit instruction flow semantics.


No. You have chosen to interpret loop and recur in this way, but that is not how Clojure understands them. 


recur is simply a flag for a tail-recursive call, functional as you like.
loop is a gloss on defining and applying a function.


We could define loop as a macro in terms of fn:

(defmacro loop [bindings &amp; expressions]
  (let [[bindees values] (-&gt;&gt; bindings
                              (partition 2)
                              (apply map vector))]
    `((fn ~bindees ~@expressions) ~@values)))


The real loop macro checks the syntax of bindings. I've not bothered. And it handles destructuring explicitly. I've left it for fn to do.