【问题标题】:Why does this usage of recur in Clojure cause a crash?为什么在 Clojure 中使用 recur 会导致崩溃?
【发布时间】:2016-11-23 20:09:35
【问题描述】:

我有这个数据结构:

(def initial-map {:name "Root"
                  :children [{:name "Child1" :children [{:name "Grandchild1"}]}
                             {:name "Child2"}
                             {:name "Child3"}]})

我需要把它变成这样的东西:

[["Root" 0] ["Child1" 1] ["Child2" 1] ["Child3" 1] ["Grandchild1" 2]]

其中的数字代表数据结构中节点的深度。

我写了这个函数来尝试从第一个到第二个:

(defn node-xform [ret nodes depth]
  (if empty? nodes)
  ret
  (recur (conj ret (map #(vector (:name %) depth) nodes))
         (flatten (map #(:children %) nodes))
         (inc depth)))

我这样称呼它

(node-xform [] (vector initial-map) 0)

但是当我这样做时,它要么超时,要么让我的电脑崩溃……我做错了什么?

【问题讨论】:

    标签: recursion clojure tree


    【解决方案1】:

    if 表单应如下所示:

    (if conditional-expr true-expr false-expr)
    

    false-expr 实际上是可选的,默认值为nil(如果不使用),但我认为这不是您想要的。看起来你想在nodes 为空时返回ret,否则recur:

    (defn node-xform [ret nodes depth]
      (if (empty? nodes) ; <-- fixed this line
        ret
        (recur (conj ret (map #(vector (:name %) depth) nodes))
               (flatten (map #(:children %) nodes))
               (inc depth)))) ; <-- added another close-paren here for the "if"
    

    我实际上并没有测试它是否会返回您的预期答案,但这至少可以解决您的无限递归问题。

    您的代码会导致无限循环,因为node-xform 总是 执行recur 形式,这会导致无限尾递归。更正 if 表单的语法使得 recur 表达式仅在 nodes 非空时执行。

    【讨论】:

      猜你喜欢
      • 2021-06-28
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-03
      • 1970-01-01
      相关资源
      最近更新 更多