延迟序列在消耗堆栈的递归调用中不起作用

时间:2015-10-22 17:39:16

标签: recursion clojure lazy-evaluation

我找到了一个简单(但效率低)的问题解决方案,基本上可以在Clojure中这样编写:

(defn make-someof [data]
  (fn sumf
    ([x n ds]
     (if (= n 1)
       (if (some #{x} ds) 1 0)
       (reduce + (for [m (filter #(< % n) ds)]
                   (sumf (- x m) (dec n) (disj ds m))))))
    ([x n] (sumf x n data))))

可以像这样调用:

((make-someof #{1 2 3 4 5 6}) 7 2)

但事实证明,make-sumof函数的reduce部分中的表单只被评估一次。 (即filter形式中有6个值只能为它的第一个值迭代!)

我也尝试在doall表单上使用for,从而强制它被计算,但是递归调用到达第一个表单时(当条件(= n 1)被保持时)结果表达式(在本例中为(if (some #{x} ds) 1 0)形式中的1)作为整个调用链的结果返回。

这对我来说没有意义 也许我犯了一个大错误,或者这是Clojure中的一个错误?

注意:此函数应该计算数字7可以写成的方式的数量,作为来自特定不同数字的2个其他数字的总和(在这种情况下为#{1 2 3 4 5 6})。
/> 我很想弄清楚这里发生了什么,因为这个函数可以用loop形式编写。

1 个答案:

答案 0 :(得分:2)

您的过滤谓词#(< % n)旨在从大于剩余目标总和的可用加数集中删除数字,而是测试小于加数n的加数。请尝试使用#(< % x)