【问题标题】:Understanding the input of the lazy quicksort presented in The Joy of Clojure了解 Clojure 的乐趣中介绍的惰性快速排序的输入
【发布时间】:2014-07-31 09:10:05
【问题描述】:

我从 Clojure 的喜悦中复制了惰性快速排序实现 并在循环后添加了两个 println 语句,以更好地理解输入的工作原理(参见底部的实现)。

运行 (qsort [2 1 4 3]) 时,我得到以下输出:

Work: = ([2 1 4 3]) =
Part: = [2 1 4 3] & nil =
=pivot:  2 =
Work: = ([2 1 4 3]) =
Part: = (1) & (2 (4 3)) =
[...]

正如预期的那样。我不明白的是Work的结构。 Work 怎么可能只是一个包含向量的列表,而part & parts 怎么可能是(1) & (2 (4 3))Work不应该有以下结构[(1) (2 (4 3))]吗?


完整性的快速排序实现:

(defn sort-parts
  "Lazy, tail-recursive, incremental quicksort. Works against and
creates partitions based on the pivot, defined as 'work'."
  [work]
  (lazy-seq
   (loop [[part & parts] work]
     (println "Work: =" work "=")
     (println "Part: =" part "&" parts "=")
     (if-let [[pivot & xs] (seq part)]
       (do (println "=pivot: " pivot "=")
           (let [smaller? #(< % pivot)]
             (recur (list*
                     (filter smaller? xs)
                     pivot
                     (remove smaller? xs)
                     parts))))
       (when-let [[x & parts] parts]
         (println "output")
         (cons x (sort-parts parts)))))))

(defn qsort [xs]
  (sort-parts (list xs)))

【问题讨论】:

    标签: algorithm clojure


    【解决方案1】:

    你的

    (println "Work: =" work "=")
    

    不会打印您在loop 表单中看到的work

    它打印sort-parts 参数列表中绑定的外部work。仅当调用 sort-parts 时才会更改。

    要获得预期的结果,请更改:

     (loop [[part & parts] work]
    

     (loop [[part & parts :as work] work]
    

    这样你就可以将工作绑定到整个循环参数列表。

    【讨论】:

    • 谢谢!现在我也看到了。
    • 我仍在寻找源代码以解释为什么会发生这种情况。如果我发现了什么,我会更新答案。
    • 我认为这是有道理的,循环带来了它的绑定形式,只有绑定形式的本地人才能被绑定。 work 在这种情况下不是绑定的一部分,因此不会创建循环上下文中的本地。因此返回 sort-parts 定义的 clojure 中的本地 work
    • 你是对的。我不知道为什么突然我认为将绑定表单的表达式端作为绑定是一个好主意;)
    • loop 在这个例子中看起来太像一个函数了:-)。
    猜你喜欢
    • 1970-01-01
    • 2011-02-11
    • 2012-08-23
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多