Clojure样式问题:循环和递归组合

时间:2019-06-30 14:36:37

标签: recursion clojure

“ Clojure的喜悦”,第二版中,第133页介绍了quicksort的代码,我很难理解。我有rewritten it要更清楚(至少对我自己来说)。

以下是原图:

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

这是重写的代码:

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

测试:

(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]])))

所以,它有效。

两个功能基本相同。

但是我对此感到不好。 recur和完全递归的同时使用以及完全递归路径在同一函数的中间“留下”循环的感觉很奇怪,就像非结构化代码丢弃了一个好的胖GOTO。

这是供参考的表达式树:

quicksort function expression tree

我们离降低beta的目标还很远。只能使用显式指令流语义来理解“减少”。好的,现实符合柏拉图式的理想。

循环递归/完全递归应该看起来像这样吗?这是可以改进的样式问题吗?

0 个答案:

没有答案